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.
- PARTIAL_WAKE_LOCK vs SCREEN_DIM_WAKE_LOCK en el subproceso de descarga
- ¿Debería llamar a WakeLock antes de crear una notificación?
- ¿El sistema operativo Android libera un wakelock si la aplicación o el servicio que lo contiene se destruye?
- Android - ¿Cómo puedo despertar el teléfono de un sueño duro para tomar una foto?
- ¿Traer la aplicación al frente, activar la visualización y desbloquear desde AlarmManager?
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
- Crecer
- En el inicio
- En resumen
- Una interrupción
- En la parada
- En el inicio
- 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.
- Preguntas para principiantes: Wakelocks
- Desactivar el dispositivo cuando la aplicación solicite al usuario
- Unity3D Android Lockscreen no se muestra cuando la pantalla se agota. (Wakelock?)
- Ayuda con PROXIMITY_SCREEN_OFF_WAKE_LOCK en Android
- ¿Es posible tener varias cerraduras de la estela?
- AlarmManager y WakeLock
- ¿Un GCM-App realmente necesita un wakelock?
- Despierta Android Phone / tablet?
- 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) } } } }
-
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{ } }
- ViewPager setCurrentItem (pageId, true) no suaviza el desplazamiento
- Establecer la anchura de vista mediante programación