¿Cómo proceso las emisiones que se enviaron mientras mi actividad se detuvo?

Mi actividad inicia un servicio que ejecuta CountDownTimer. El temporizador devuelve las emisiones a la actividad mientras cuenta. La actividad procesa las emisiones en el método onReceive de un BroadcastReceiver. Todo esto funciona bien.

Mi problema se produce cuando suceden los siguientes eventos en este orden:

  1. La aplicación se ha detenido (a través de onPause ())
  2. Terminaciones del temporizador
  3. Se reanuda la aplicación (via onResume ())

Cuando se reanuda la aplicación, el servicio ya no envía emisiones, por lo que la actividad no sabe cuánto tiempo queda en el temporizador o si está terminado . Esto evita que la actividad actualice la interfaz de usuario.

He intentado una docena de maneras de lidiar con esto, y leer a través de muchas preguntas y respuestas de desbordamiento de pila, pero aún no he encontrado una solución. Yo creo que hay una manera de recoger una emisión que fue enviada mientras la actividad no estaba activa, pero todavía tengo que encontrar una manera.

Para el registro, aquí está mi código de actividad y servicio relevante:

Activity.java

// Start service timerIntent.putExtra("totalLength", totalLength); this.startService(timerIntent); // ... // BroadcastReceiver private BroadcastReceiver br = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent.getExtras() != null && inSession) { session.setRemaining(intent.getExtras().getLong("millisUntilFinished")); updateProgress(); } } }; // ... // onResume @Override public void onResume() { super.onResume(); registerReceiver(br, new IntentFilter(TimerService.COUNTDOWN_TS)); } 

servicio java

 @Override public int onStartCommand(Intent intent, int flags, int startId) { long length = intent.getExtras().getLong("totalLength"); countDownTimer = new CountDownTimer(length, 1000) { @Override public void onTick(long millisUntilFinished) { timerServiceIntent.putExtra("millisUntilFinished", millisUntilFinished); sendBroadcast(timerServiceIntent); } @Override public void onFinish() { } }; countDownTimer.start(); return super.onStartCommand(intent, flags, startId); } 

¿Cuál es la mejor manera de procesar las emisiones que envió el servicio mientras se detuvo la actividad?

Utilice BroadcastReceiver para almacenar la última petición (SharedPreferences quizás) que recibió y compruebe cuando se inicia la Actividad.

Alternativamente, en lugar de procesar una cuenta regresiva usando transmisiones, sólo almacene el tiempo que la cuenta regresiva terminaría. La actividad puede entonces manejar la cuenta atrás por sí misma, ya que sabe cuándo debe terminar. El uso de un servicio y las transmisiones parecen ser un poco más de ingeniería para una tarea tan simple.

Actualización: De la forma en que ha descrito su tarea, veo que necesita manejar dos escenarios. Así es como lo haría.

Asumiendo que "XYZ" es el servicio \ intento \ lo que comienza la cuenta regresiva y "ABC" es la Actividad que muestra el progreso. (ABC y XYZ podría ser la misma actividad si eso es lo que quería)

Requisitos: Cuando comience la cuenta atrás, haría XYZ almacenar el tiempo que la cuenta atrás debería terminar en SharedPreferences.

  1. ABC ya se está ejecutando cuando comienza la cuenta regresiva. Como dijo Commonsware, el modelo Eventbus es excelente para manejar este escenario mientras XYZ y ABC estén funcionando en el mismo proceso. Simplemente dispare un evento para leer el valor de preferencia y cuente hasta el tiempo especificado. Si el usuario cierra ABC y lo vuelve a abrir, se iniciará el escenario 2.

  2. ABC no está funcionando. Compruebe en OnResume si ha transcurrido el tiempo de cuenta regresiva. Si no, configure ABC para volver a mostrar la cuenta regresiva. Si no hay cuenta atrás activa, haga otra cosa.

Si también necesitas hacer algo cuando la cuenta regresiva ha transcurrido sin importar si tienes una interfaz de usuario activa, entonces la sugerencia de AlarmManager de Commonsware es perfecta.

Imaginemos por un momento que usar un Service con un CountDownTimer para rastrear algún paso del tiempo con el propósito de actualizar una Activity es una buena idea. No está fuera de la cuestión, suponiendo que el Service está haciendo algo de verdad y esta cosa de tiempo es un subproducto.

Una actividad no recibe transmisiones mientras se detiene, principalmente por razones de rendimiento / batería. En su lugar, la actividad debe extraer el estado actual cuando se inicia y, a continuación, utilizar eventos (por ejemplo, las emisiones actuales) para informarse de los cambios en los datos mientras se inicia.

Esto sería simplificado usando algo como el evento de Greenrobot EventBus y sus eventos pegajosos, ya que la actividad obtendría automáticamente el último evento cuando se suscriba a obtener eventos. El uso de EventBus de greenrobot para este propósito también reduciría los problemas de seguridad y rendimiento que está introduciendo al utilizar las transmisiones del sistema para hablar entre dos clases Java en el mismo proceso.

Además, se adhieren a los pares del ciclo de vida. onResume() no es la contraparte de onStop() . onStart() es la contrapartida de onStop() ; onResume() es la contraparte de onPause() . Inicializar algo en un par (por ejemplo, onResume() ) y limpiarlo en el otro par (por ejemplo, onStop() ) corre el riesgo de errores de doble inicialización o doble limpieza.

¿Cuál es la mejor manera de procesar las emisiones que envió el servicio mientras se detuvo la actividad?

El uso de intentos de difusión pegajosa del servicio y luego recuperarlos de la actividad sería una forma de procesar las emisiones que el servicio envió mientras se detuvo la actividad. Sólo puedo ofrecer eso como una posible solución en lugar de reclamar que es la "mejor manera".

http://developer.android.com/reference/android/content/Context.html#sendStickyBroadcast(android.content.Intent)

Sin embargo, han quedado obsoletas desde el nivel API 21 debido a problemas de seguridad.

En lugar de utilizar la emisión Normal, puede utilizar la emisión Ordenada (enviada con Context.sendOrderedBroadcast). Para ello, junto con la definición de un BroadcastReceiver en su actividad que se requiere para definir BroadcastReceiver en su manifiesto con el mismo filtro de intenciones. Sólo el cambio es mientras se registra BroadcastReceiver en su actividad que necesita para establecer la prioridad a alta, de modo que cuando su actividad se está ejecutando y BroadcastReceiver de la actividad está registrada se llama primero y dentro onReceive de este BroadcastReceiver puede utilizar abortBroadcast para obtener el BroadcastReceiver llamado que se define en su manifiesto android. Ahora, cuando su actividad no está ejecutando el BroadcastReceiver definido en su manifiesto android se llamará. Así que de esta manera usted puede tener el estado y si lo desea puede mostrar las actualizaciones al usuario por notificación, incluso si su actividad no se está ejecutando.

  • Cómo solucionar el error: No se pudo encontrar el método onClick (View) en un padre o ancestro Contexto para android: onClick
  • Android - estilo de botón predeterminado
  • Cómo detectar si es el botón Recents, el modo Multi Window o el botón home onUserLeaveHint ()
  • Java - Línea aleatoria leer
  • Compruebe la conexión a Internet activa Android
  • debug.keystore no existe
  • No se pudo encontrar el método com.google.android.gms.common.GooglePlayServicesUtil
  • Enviar int s entre Java y C
  • Cómo llamar a las actividades de un hilo no actividad?
  • Uso correcto de Classloader (especialmente en Android)
  • ¿Cómo ORMlite gestiona la herencia entre clases Java?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.