Vida de la aplicación Android: tal vez infinita?

Estoy desarrollando una aplicación diseñada para transformar un teléfono Android en un dispositivo remoto que se ejecuta sin la acción del usuario. En el momento en que la aplicación es realizada por una actividad que establece AlarmManager para ejecutar un servicio (clase dentro del proyecto) cada X minutos.

Todo esto funciona bien, pero de vez en cuando después de 5-6 días continuos corriendo la aplicación se bloquea (actualmente no sé por qué, porque no puedo conseguir el teléfono ahora). No es un problema de conexión (lo sé) y el teléfono sigue funcionando (conectado a la CA). Lo único que puedo suponer es que la aplicación está inactiva.

No creo que esto se deba a un error, porque la depuración de prew no me da ningún error.

Así que debo suponer que android ha matado a la actividad (el sistema necesita más memoria?) Y como la imagen de explicar no hay forma de copia de seguridad.

Diagrama de flujo

Pero tengo una duda: en mi aplicación la actividad no importa, porque todo el trabajo lo hace el servicio. El servicio en sí es llamado por un administrador de alarmas y en el tiempo entre dos llamadas el servicio es finalizado por StopSelf ().

En mi caso el sistema puede matar mi horario de servicio de administrador de alarmas?

¿Qué puedo hacer para que el servicio comience por Alarm Manager para siempre?

( ATENCIÓN : actualmente todavía hay un WAKE LOCK pero esto solo considera la ejecución del servicio Espero que haya entendido que el servicio se llama cada x minutos por administrador de alarmas y que terminó … Quiero realizar estas operaciones para Un tiempo indefinido)

[No he publicado el código fuente porque es demasiado largo]

3 Solutions collect form web for “Vida de la aplicación Android: tal vez infinita?”

Lork,

Después de luchar con problemas similares yo mismo, puedo tener algunos consejos para usted. Supongo que usted está utilizando su dispositivo Android como una especie de control remoto 'incrustado', que realiza sus funciones con la mínima interacción del usuario. Creo que usted es el 95% y sólo hay que hacer algunos cambios arquitectónicos. Como no ha proporcionado código, explicaré en términos abstractos en lugar de dar ejemplos de código.

CommonsWare es correcto que necesitas usar AlarmManager, pero sospecho que ya lo sabías. Un par de comentarios de fondo primero, sólo para asegurarse de que todo es comprensible. Las alarmas creadas por AlarmManager existen a nivel de sistema, es decir, pueden existir más allá del ciclo de vida de la actividad y la aplicación que las creó. Si configura una alarma pero no desea que se apague si la aplicación cambia de estado (por ejemplo, después de haberla destruido), puede cancelarla con alarmManager.cancel (pendingIntent): simplemente cree los intents y el administrador de alarmas con Los mismos parámetros y Android coincidirá con la alarma). Del mismo modo, BroadcastReceivers se registran a nivel de sistema (al menos si se declaran en manifest.xml) y pueden existir más allá del ciclo de vida de la actividad y la aplicación que los creó. Una vez más, si desea asegurarse de que un BroadcastReceiver no se dispara en respuesta a un evento que se produce después de que su aplicación ha cambiado de estado (por ejemplo, después de que se ha destruido), debe anular el registro explícitamente en código. Si se registró mediante programación, utilice context.unregisterReceiver (broadcastReceiver); Si se registró estáticamente en el manifiesto no es tan fácil – tendrá que recuperar el receptor con PackageManager y ComponentName (véase: Android – cómo anular el registro de un receptor creado en el manifiesto? ) – y recuerde que tendrá que re- Active el receptor si lo necesita de nuevo.

Usted dice que ya ha configurado su alarma. Asegúrese de especificar ELAPSED_REALTIME_WAKEUP o RTC_WAKUP para el tipo de alarma para asegurarse de que se ejecuta incluso cuando el teléfono está en modo de suspensión. También dice que ya ha creado el BroadcastReceiver asociado para manejar el evento de alarma. BroadcastReceiver debe hacer un mínimo de trabajo, por lo que debe manejar cualquier procesamiento en un hilo separado o mediante el lanzamiento de un servicio. Usted optó por lanzar un servicio y terminarlo usando stopSelf () cuando haya terminado, para que no utilice los recursos del sistema. Hasta aquí todo bien.

Esto está bien cuando la aplicación se está ejecutando, sin embargo, como se requiere algo que se ejecuta de forma fiable por un período indefinido, es necesario asegurarse de que gestionar las situaciones de excepción donde se ha detenido, el dispositivo está durmiendo, la aplicación se ha estrellado / Terminated, o el dispositivo ha reiniciado (y cualquier otro escenario de excepción que pueda pensar). Aquí están los problemas que he identificado que usted necesita dirigir:

Primero: WakeLock sólo está garantizado durante la duración del método onReceive () de BroadcastReceiver. Después de que se haya terminado, el dispositivo podría volver a "dormir" incluso si su servicio no ha comenzado o incluso completado, por lo que necesita para crear un WakeLock, pasarlo al servicio y liberarlo antes de detener el servicio. (Nota: para su aplicación, necesita un PARTIAL_WAKE_LOCK). Tenga mucho cuidado con WakeLocks – asegúrese de que sólo tiene un WakeLock por el tiempo mínimo requerido y asegúrese de que lo suelte, ya que su uso puede conducir a un excesivo drenaje de la batería). Consulte http://www.netmite.com/android/mydroid/development/pdk/docs/power_management.html para obtener un ejemplo de cómo usar WakeLocks.

En segundo lugar: Si reinicia su alarma en código (en lugar de definir una repetición automática), haga esto en el método OnReceive () de BroadcastReceiver o como la primera cosa en el servicio que ha lanzado – esto asegurará que la alarma se repita, Independientemente del estado de la aplicación o dispositivo.

Tercero: Asegúrese de que cualquier Contexto que utilice va a ser valores no nulos. Puede obtener dinámicamente el contexto en el servicio mediante getApplicationContext (). De lo contrario esto puede lograrse pasando EXPLICITAMENTE el Contexto de su aplicación a la alarma y asegurarse de que se transmite completamente a través de BroadcastReceiver y los subprocesos asociados y los Servicios. Si ha almacenado de forma estática Contexto en su aplicación para que pueda recuperarla en cualquier lugar, esto devolverá un valor nulo si la aplicación ha finalizado. Si utiliza el Contexto (por ejemplo para recuperar un recurso, acceder a una base de datos, etc.) y es nulo, provocará una excepción de puntero nulo y el Servicio o BroadcastReceiver se bloqueará. Creo que esta es la razón más probable para que sus receptores Broadcast no funcionen cuando su aplicación haya finalizado.

Cuarto: Es posible que desee hacer referencias a ResourceIDs (por ejemplo, R.drawable.icon) en su Servicio o BroadcastReceiver totalmente calificado (.drawable.icon) o generado desde el contexto pasado. Todavía no he encontrado esto necesario, pero sospecho que puede ser prudente.

Quinto: Implementar un BroadcastReceiver separado para manejar un escenario de reinicio del dispositivo (evento ON_BOOT_COMPLETE). Usted podría conseguir este receptor para volver a lanzar la aplicación, si es apropiado o podría lanzar un servicio para comprobar que su aplicación se supone que está activa, configurar los parámetros necesarios y configurar las alarmas pertinentes, a continuación, terminar con stopSelf () O simplemente establecer la alarma de nuevo y dejar que el receptor de manejar todo. Recuerde asegurarse de que el servicio tiene un WakeLock durante su duración y de liberar el WakeLock cuando esté completo. Si no acaba de reiniciar la aplicación o un servicio (declarado como parte de su aplicación), también debe almacenar de forma estática el Contexto correcto como un atributo de clase en su BroadcastReceiver, si lo necesita, para que esté disponible para acceder Recursos.

Un par de otras cosas que usted puede desear considerar: Como su disposición es remota, consideraría seriamente almacenar cualquier datos persistentes en tablas de la base de datos de SQLite. Esto asegurará que los datos sean recuperables entre las terminaciones de la aplicación y los reinicios del dispositivo, sin tener que regenerarlo. Si su aplicación se comunica con un servicio de servidor, considere el uso de notificaciones push para la comunicación iniciada por el servidor, en lugar de hacer que la aplicación periódicamente encuesta. Push Notificaciones también se puede utilizar para "despertar y lanzar servicios y aplicaciones", por lo que podría ser utilizado como parte de un mecanismo remoto para consultar el estado del dispositivo y su aplicación. Este enfoque también es más eficaz en términos de energía y oportuno. Publique información en LogCat en los puntos clave de su código para depurar. Si la aplicación termina, entonces adb detiene el seguimiento del código fuente que se ejecuta para el receptor y el servicio, pero LogCat sigue funcionando, por lo que se puede utilizar para comprobar la ruta a través del código y los valores de la variable.

Otras personas pueden tener mejores maneras de abordar estas cuestiones o algunos otros punteros (yo sin duda estaría muy feliz de ver otra entrada), pero espero que estas ideas son útiles y buena suerte!

El punto detrás de usar AlarmManager con un servicio es iniciar un servicio que se ejecutará brevemente, entonces el servicio desaparece (por ejemplo, un IntentService ). Si usted va a tratar de tener un servicio eterno, no necesita AlarmManager , y su servicio será cerrado por Android después de un período de tiempo.

Si reescribe su aplicación para que no necesite un servicio eterno, sino que utilice AlarmManager tal como estaba previsto, debería tener una mejor supervivencia.

Creo que lo que Lork quiere lograr es similar a algo con lo que también estoy luchando. Quiere que el administrador de alarmas active un receptor de difusión que maneje la alarma, incluso cuando la aplicación de la que forma parte, haya finalizado (por ejemplo, por el sistema operativo Android).

Por ejemplo: La aplicación establece una alarma con un tipo de ELAPSED_REALTIME_WAKEUP o RTC_WAKUP y tiene un Broadcast Receiver para manejarlo cuando se activa, a través de un Intent que hace referencia al contexto de la aplicación ya la clase Broadcast receiver. El receptor se declara como un en el manifiesto de aplicación.

En circunstancias normales, cuando la aplicación está en funcionamiento o en pausa, cuando la alarma se apaga, el receptor de difusión se dispara, despierta el dispositivo y reanuda la aplicación según sea necesario, y la alarma se maneja. Sin embargo, si la aplicación ha sido destruida (por ejemplo por el sistema operativo), la alarma seguirá apagándose (ya que todavía está registrada), pero no se activará el receptor de difusión y LogCat mostrará una excepción de puntero nulo (supongo que porque La referencia a la aplicación ya no está en memoria). Esto ocurrirá, incluso si se ha pasado el Contexto.

¿Soy (y supongo que Lork) falta una estrategia fácil aquí? ¿O acaso no es posible? ¿Puede existir un receptor de difusión por sí solo y activar la aplicación si es necesario?

Uno, la estrategia imperfecta que he estado jugando, es mover todo el acceso a los datos de la aplicación en un proveedor de contenido, y tener una aplicación de bajo perfil independiente que sólo implementa el receptor de difusión – activar un servicio para hacer el trabajo y acceder a los datos de la aplicación que Requiere a través del proveedor de contenido. Esto todavía estaría sujeto a ser terminado por el sistema operativo, pero sería menos probable.

  • Android ¿cuánto tiempo nuestra actividad estará allí en la pila
  • La aplicación se comporta diferente después de salir y volver a entrar
  • ¿Cómo comprobar si una actividad es la última en la pila de actividades de una aplicación?
  • ¿Cómo funcionan los ciclos de vida de la actividad de Android en relación con la aplicación completa?
  • Método de clase de aplicación Android onCreate que se llama varias veces
  • ¿Cómo probar el código construido para salvar / restaurar el ciclo de vida de una actividad?
  • Android - Tiempo de vida de las diferentes opciones de almacenamiento
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.