启动活动后立即调用OnPause和OnStop()

Har*_*ris 43 android activity-lifecycle wakelock android-activity

我有一项活动需要在启动时打开屏幕(如果是关闭).所以在onCreate中,我有:

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);
Run Code Online (Sandbox Code Playgroud)

在广播接收器的wakelock的帮助下使用它,我能够在广播接收器启动时显示我的活动.

但问题很奇怪,活动生命周期以这种方式调用,onPause()和onResume在启动活动后立即调用

  1. 的onCreate
  2. 在onStart
  3. 的onResume
  4. 在onPause
  5. 的onStop
  6. 在onStart
  7. 的onResume

所以问题出在启动和恢复调用两次,在停止也调用,我想在onStop()中实现一些逻辑,但是,这样的行为应用程序将无法正常工作.

编辑

我发现问题只是由于标志FLAG_SHOW_WHEN_LOCKED.当设备被锁定时 它只会在活动开始前锁定设备时发生.

PS我正在使用带有广播接收器的报警管理器,然后从广播接收器开始活动.

Man*_*ani 47

  • 让我们理解为什么生命周期方法被多次调用.

以下是ActivityThread中记录的重要代码注释,它负责执行应用程序进程的活动.

我们通过正常启动来实现这一点(因为活动期望在它们第一次运行时,在它们显示窗口之前经历onResume()),然后暂停它.

之后onResume,活动窗口将附加到窗口管理器并被onAttachedtoWindow调用.如果屏幕打开,活动窗口将获得焦点并onWindowFocusChanged使用true参数调用.来自docs:

请记住,onResume不是您的活动对用户可见的最佳指标; 诸如键盘锁之类的系统窗口可以在前面.使用onWindowFocusChanged(boolean)可以确定您的活动对用户可见

在报告的问题中,屏幕如果关闭.因此,活动窗口不会获得焦点,这会导致onPause调用活动的方法,然后调用onStop方法,因为活动窗口不可见.

由于WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON在活动窗口上设置了标志,因此窗口管理器服务使用电源管理器api打开屏幕.以下是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;
        }
        ...
}
Run Code Online (Sandbox Code Playgroud)

屏幕打开后onStart,并onPause再次调用.

因此:onCreate - onStart - onResume - onPause - onStop - onStart - onPause.

这可以通过锁定设备并使用adb命令或启动活动来验证eclipse.

  • 理想解决方案

如果您启动任务,则onCreate需要将其停止onDestory(如果任务仍处于待处理状态).同样,对于onStart这将是onStoponResume这将是onPause.

  • 解决方法

如果不能按照上述协议,你可以检查的活动窗口焦点使用状态hasWindowFocusonPause方法.通常,活动窗口焦点状态将为真onPause.在屏幕关闭或屏幕打开并显示键盘的情况下,活动窗口焦点将为false 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
    }
}
Run Code Online (Sandbox Code Playgroud)