Cómo obtener un servicio "enlazado" de Android para sobrevivir a un reinicio de la configuración

Tengo una aplicación para Android con algún estado global (incluyendo algunos grandes SoundPool s) que requiere limpieza, por lo que las siguientes respuestas a mi pregunta anterior Estoy tratando de manejar esto utilizando un Service .

Actualmente onStart un servicio vinculado al que todas las actividades se vinculan / se onStart en onStart / onStop , y cuando todas las actividades se detienen, el servicio se desvincula y onDestroy llama al servicio, dejándome liberar las SoundPools .

Dado que el ciclo de vida de la actividad se superpone deliberadamente (la nueva actividad onStart dispara antes de que se active onStop ), al navegar entre actividades siempre hay al menos una actividad enlazada y el servicio permanece activo.

Sin embargo, si roto la pantalla para provocar un reinicio de la configuración, el servicio está desvinculado y muere cuando la actividad activa pasa por el ciclo de vida de reinicio de la configuración.

¿Cómo puedo evitar esto y mantener el servicio vivo a través de reinicios, mientras que todavía permite que el servicio muera cuando se detiene la aplicación?

Ok, ya que esto ha demostrado ser una pregunta especialmente difícil, pensé que publicaría mi solución aquí en caso de que alguien nunca golpea algo similar.

Hay claramente varias maneras de abordar esto, pero el más simple que he usado es tener un servicio "iniciado" que decide cuando cerrarse. Mis actividades cada bind / unbind al servicio, y después de un retraso de tiempo establecido (he usado 1 minuto) el servicio se cerrará si no más actividades han obligado – esto cubre si el usuario deja de usar la aplicación más si hay Cualquier error fatal de actividad.

El temporizador de apagado está programado dentro de onUnbind() y se cancela en onStartCommand() , onBind() , onRebind() . Si se dispara, cierra el servicio de forma limpia, lo que a su vez desencadena una limpieza del estado gestionado en el servicio onDestroy() .

Mi código de Service es el siguiente:

 public class LocalStateService extends Service { /** The binder to give to clients. */ private final IBinder binder = new LocalStateBinder(); /** Used for time-delayed shutdown. */ private final Handler handler = new Handler(); /** * Called before starting or the first binding. */ @Override public void onCreate() { // initialise state... } /** * Called when this service is explicitly started. * @param intent The intent passed on starting, unused * @param flags Startup flags, unused * @param startId Identifies each start request * @return Desired restart behaviour */ @Override public int onStartCommand(Intent intent, int flags, int startId) { cancelShutdown(); // if killed, we would like Android to restart this service, but don't bother re-delivering // the original intent used to start the service return START_STICKY; } /** * Called when the first client binds. * @param intent The intent passed on binding * @return The binding to use */ @Override public IBinder onBind(Intent intent) { cancelShutdown(); return binder; } /** * Called when the first of previous clients re-binds. * @param intent The intent passed on binding */ @Override public void onRebind(Intent intent) { cancelShutdown(); } /** * Called when all clients have unbound. * @param intent The first intent originally passed on binding * @return Whether this service should be notified of rebinding */ @Override public boolean onUnbind(Intent intent) { // post a callback to be run in 1 minute handler.postDelayed(delayedShutdown, 1000L * 60); // we do want onRebind called when clients return return true; } @Override public void onDestroy() { // state cleanup... } private Runnable delayedShutdown = new Runnable() { @Override public void run() { LocalStateService.this.stopSelf(); } }; /** * Cancel any shutdown timer that may have been set. */ private void cancelShutdown() { // remove any shutdown callbacks registered handler.removeCallbacks(delayedShutdown); } } 

En lugar de hacerlo desde mi Application , mi actividad principal llama a startService(..) En onCreate() ya que esto funcionará tanto para el inicio inicial como cuando el usuario vuelva a usar una aplicación en pausa (donde el servicio puede o no haber decidido Para cerrarse).

Cada actividad entonces se une y se desvincula como por normal.

Encontre eso:

  • Al navegar entre actividades, no se cancela ninguna devolución de llamada de servicio. Dado que el ciclo de vida de la actividad se superpone, estos son enlaces / desenlaces secundarios

  • Cuando una actividad se reinicia (por ejemplo, la rotación de la pantalla), el servicio recibe una onUnbind() y una llamada onRebind()

  • Al hacer una pausa en la aplicación (p. Ej., Presione la tecla de inicio de la actividad principal) o al terminar (por ejemplo, presione atrás de la actividad principal), el servicio recibe onUnbind() .

  • Algunos objetos parcelables reunidos en un intento / paquete podrían interferir y comprometer la lectura de Intención / Bundle?
  • Android 6.0 (Marshmallow): Cómo jugar notas de midi?
  • Cómo obtener el espaciado de caracteres de fuente en Android
  • Necesito ayuda con Android y Java
  • Enum VS Static Class (Normal y con valores de cadena)
  • SMS raw pdu en Android
  • HttpUrlConnection configuración Rango en Android se ignora
  • No se puede obtener String.split () para funcionar como se esperaba en android
  • Android: pesadas operaciones de DB con diálogo de progreso
  • ¿Por qué MediaPlayer.seekTo (t) no va al instante especificado exacto "t"?
  • Patrón de Android AsyncTask / doInBackground
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.