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
.
- ClientProtocolException en httpClient.execute (httpget, responseHandler)
- Espacio izquierdo en la barra de herramientas con SearchView android studio
- ¿Es el desarrollo de Android en C / C ++ más rápido que Java?
- Transferencia de Bluetooth La aplicación se detiene después de usar InputStream.read () sin error
- ¿Por qué los paquetes del módulo de biblioteca no existen en la compilación, incluso cuando Android Studio no muestra errores en el código?
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?
- ¿Por qué utilizar un hashmap?
- Enviar eficientemente int a través de sockets en Java
- ViewPager ¿Fragmentos que se destruyen con el tiempo?
- Android OpenCV con MatOfKeyPoint y detección de feature2d
- ¿Está haciendo la llamada de red segura en ArrayAdapter?
- ¿Cuál es la diferencia entre commit () y commitAllowingStateLoss () en Fragments
- Cómo obtener un mensaje de devolución de servicio de Android desde un plugin de teléfono
- No se muestran trazas de registro y bloqueo de bloqueo en Android Studio
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 llamadaonRebind()
-
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()
.
- Metadatos de Android desde el manifiesto que devuelve null
- La aplicación se está bloqueando después de capturar la imagen con las intenciones