OnPause y OnStop () llamados inmediatamente después de iniciar la actividad

Tengo una actividad que necesita activar la pantalla (si está desactivada) cuando se inicia. Así que en onCreate, tengo:

this.getWindow().setFlags( WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); 

Utilizando esto con la ayuda de wakelock en el receptor broadcasr, puedo hacer que mi actividad se muestre cada vez que se inicia desde el receptor de difusión.

Pero el problema es muy extraño, las llamadas del ciclo de vida de la actividad de esta manera, onPause () y onResume inmediatamente después de iniciar la actividad

  1. Crecer
  2. En el inicio
  3. En resumen
  4. Una interrupción
  5. En la parada
  6. En el inicio
  7. En resumen

Así que el problema está en el inicio y en el reanudar llamar dos veces, con en parada también llamando, quiero implementar alguna lógica en onStop () pero, con tal aplicación de comportamiento no funcionará correctamente.

Editar

Encontré el problema sólo es debido a la bandera FLAG_SHOW_WHEN_LOCKED. Y cuando el dispositivo está bloqueado. Y sólo ocurre cuando el dispositivo está bloqueado antes de que la actividad se inicie.

PS Estoy usando el administrador de alarma con el receptor de difusión, y luego inicia la actividad de receptor de difusión.

  • Vamos a entender por qué los métodos del ciclo de vida se llaman varias veces.

Aquí hay un comentario de código importante documentado en ActivityThread , que es responsable de ejecutar las actividades del proceso de solicitud.

Logramos esto pasando por el inicio normal (porque las actividades esperan pasar por onResume () la primera vez que se ejecutan, antes de que su ventana se muestre), y luego detenerlo.

Justo después de onResume , la ventana de actividad se adjunta al gestor de ventanas y se invoca onAttachedtoWindow . Si la pantalla está onWindowFocusChanged , la ventana de actividad obtendrá el foco y se invocará onWindowFocusChanged con el parámetro true . De los documentos :

Tenga en cuenta que onResume no es el mejor indicador de que su actividad es visible para el usuario; Una ventana del sistema tal como el bloqueo del teclado puede estar delante. Utilice onWindowFocusChanged (boolean) para saber con certeza que su actividad es visible para el usuario

En el caso informado, la pantalla está desactivada. Por lo tanto la ventana de la actividad no conseguirá el foco, que da onPause método onPause la actividad que consigue llamado seguido por método de onStop , como la ventana de la actividad no es visible.

Dado que el indicador WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON se establece en la ventana de actividad, el servicio de gestor de ventanas activa la pantalla mediante el api del administrador de energía. A continuación se muestra el código WindowManagerService :

 public int relayoutWindow(...) { ... toBeDisplayed = !win.isVisibleLw(); ... if (toBeDisplayed) { ... if ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) { if (DEBUG_VISIBILITY) Slog.v(TAG, "Relayout window turning screen on: " + win); win.mTurnOnScreen = true; } ... if (mTurnOnScreen) { if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); mPowerManager.wakeUp(SystemClock.uptimeMillis()); mTurnOnScreen = false; } ... } 

Después de que la pantalla se enciende onStart y onPause se llaman de nuevo.

Por lo tanto: onCreate - onStart - onResume - onPause - onStop - onStart - onPause .

Esto se puede verificar bloqueando el dispositivo e iniciando la actividad mediante adb command o eclipse .

  • Solución ideal

Si inicia una tarea en onCreate , debe detenerla en onDestory (si la tarea sigue pendiente). Del mismo modo para onStart sería onStop y para onResume sería onPause .

  • Solución

Si no puede seguir el protocolo anterior, puede comprobar el estado del foco de la ventana de actividad usando hasWindowFocus en el método onPause . Normalmente, el estado de enfoque de la ventana de actividad será verdadero en onPause . En escenarios como la pantalla está desactivada o la pantalla está activada con el bloqueo de teclado visualizado, el foco de la ventana de actividad será falso en onPause .

 boolean mFocusDuringOnPause; public void onPause() { super.onPause; mFocusDuringOnPause = hasWindowFocus(); } public void onStop() { super.onStop(); if(mFocusDuringOnPause) { // normal scenario } else { // activity was started when screen was off / screen was on with keygaurd displayed } } 

Añadir android:configChanges="keyboardHidden|orientation|screenSize" Activity en su Manifest . Esto puede resolver su problema.

Utilice la clase WakeLocker. Tiene métodos para despertar la pantalla

He notado que hay un atributo de activity en AndroidManifest.xml llamado android:showOnLockScreen="true|false"

por ejemplo:

  <activity android:name="AlarmAlertFullScreen" android:excludeFromRecents="true" android:theme="@style/AlarmAlertFullScreenTheme" android:showOnLockScreen="true" android:screenOrientation="nosensor" android:configChanges="orientation|screenSize|keyboardHidden|keyboard|navigation"/> 

Busqué en la web para su documentación, pero no hay suerte, pero desde su nombre debe funcionar como el indicador de ventana WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED hacer.


El único documento que he encontrado

Especifique que una actividad debe mostrarse en la pantalla de bloqueo y, en un entorno multiusuario, en todas las ventanas de los usuarios [booleano]


Editar

Puede usted intentar por favor llamar su código de la bandera antes de llamar a super.onCreate(...)

 public class BaseActivity extends Activity { @Override protected void onCreate(Bundle bundle) { this.getWindow().setFlags( WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); //then call super super.onCreate(bundle); . . . } } 

Prueba esto. He utilizado esto y funciona bien

 PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); _wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, POWER_SERVICE); _wakeLock.acquire(); 

La solución de Manish Mulimani funcionó para mí, excepto que primero comprobar el foco de la ventana y luego llamar a través de la super.onPause ():

 public void onPause() { mFocusDuringOnPause = hasWindowFocus(); super.onPause(); } public void onStop() { super.onStop(); if (mFocusDuringOnPause) { // normal scenario } else { // activity was started when screen was off or screen was on with keyguard displayed } } 

Usted dijo que desea implementar alguna lógica en onStop (), pero con tal aplicación de comportamiento no funcionará correctamente. Usted no nos mostró exactamente lo que tiene dentro onStop (), pero creo que su lógica probablemente reinicia la actividad .. en ese caso puede implementar su lógica en onStop como eso:

 @Override protected void onStop(){ super.onStop(); //implement your code only if !STATE_OFF - to prevent infinite loop onResume <-> onStop while screen is off DisplayManager dm = (DisplayManager) this.getSystemService(Context.DISPLAY_SERVICE); for (Display display : dm.getDisplays()){ if(display.getState() != Display.STATE_OFF){ //implement your code only if device is not in "locked" state KeyguardManager myKM = (KeyguardManager) this.getSystemService(Context.KEYGUARD_SERVICE); if( !myKM.inKeyguardRestrictedInputMode()) //If needed you can call finish() (call onDestroy()) and your logic will restart your activity only once. finish(); // implement your logic here (your logic probably restarts the activity) } } } } 
  1. Otra solución que puede ayudarle será evitar onStop () y usar onWindowFocusChanged con bool hasFocus

      /** * Called when the current {@link Window} of the activity gains or loses * focus. This is the best indicator of whether this activity is visible * to the user. */ @Override public void onWindowFocusChanged(boolean hasFocus){ super.onWindowFocusChanged(hasFocus); if( ! hasFocus ){ } else{ } } 
  • Eliminar el permiso WAKE_LOCK no deseado fusionado de la biblioteca
  • ¿Cómo las notificaciones necesitan WAKE_LOCK en android?
  • ¿Necesito un bloqueo de despertador en mi transmisor-receptor si no estoy iniciando un servicio o una actividad?
  • ¿Cómo usar Wake Lock para android mediaplayer?
  • Programación de Android: GCMIntentService Stuck at WakeLock
  • Temporizador Se ralentiza en Servicio cuando se bloquea la pantalla del dispositivo
  • ¿Hay alguna manera de recibir un evento de espera de la CPU en Android?
  • Corregir el patrón para adquirir un WakeLock en un BroadcastReceiver y liberarlo en un servicio
  • GPS de seguimiento de Android y WakeLock
  • ¿Debo usar WakeLock en IntentService?
  • StandBy como actividad
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.