Android 启动Activity时唤醒系统的方法(Sleep、Dream)

今天有客户求助一个问题,说是之前在L版本还可以的唤醒系统的方案,在O版本上不行了。

他的代码的思路是这样子,首先在Activity里面aquire一个ACQUIRE_CAUSES_WAKEUP flag的wakelock,然后再设置添加window的flag WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON。

首先,如果要在Activity里面保持系统的唤醒状态,一般只要添加FLAG_KEEP_SCREEN_ON flag就可以了,这也是google建议的做法,不需要再申请wakelock。

然后从O版本开始,应用后台的行为进行了很多的限制,往往需要将应用进程提升为前台进程之后才能进行相关的业务。就本问题而言,最终的解决方案如下。

public class MainActivity extends AppCompatActivity {

    @RequiresApi(api = Build.VERSION_CODES.O_MR1)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setTurnScreenOn(true);
        KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
        keyguardManager.requestDismissKeyguard(this, null);
    }

}

主要的解决思路在于ActivityRecord的completeResumeLocked方法,在resume Activity之后,如果canTurnOnScreen为true,会通过powermanager来申请唤醒系统。

    void completeResumeLocked() {
        final boolean wasVisible = visible;
        setVisible(true);
        if (!wasVisible) {
            // Visibility has changed, so take a note of it so we call the TaskStackChangedListener
            mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
        }
        idle = false;
        results = null;
        newIntents = null;
        stopped = false;

        if (isHomeActivity()) {
            ProcessRecord app = task.mActivities.get(0).app;
            if (app != null && app != service.mHomeProcess) {
                service.mHomeProcess = app;
            }
        }

        if (nowVisible) {
            // We won't get a call to reportActivityVisibleLocked() so dismiss lockscreen now.
            mStackSupervisor.reportActivityVisibleLocked(this);
        }

        // Schedule an idle timeout in case the app doesn't do it for us.
        mStackSupervisor.scheduleIdleTimeoutLocked(this);

        mStackSupervisor.reportResumedActivityLocked(this);

        resumeKeyDispatchingLocked();
        final ActivityStack stack = getStack();
        stack.mNoAnimActivities.clear();

        // Mark the point when the activity is resuming
        // TODO: To be more accurate, the mark should be before the onCreate,
        //       not after the onResume. But for subsequent starts, onResume is fine.
        if (app != null) {
            cpuTimeAtResume = service.mProcessCpuTracker.getCpuTimeForPid(app.pid);
        } else {
            cpuTimeAtResume = 0; // Couldn't get the cpu time of process
        }

        returningOptions = null;

        if (canTurnScreenOn()) {
            mStackSupervisor.wakeUp("turnScreenOnFlag");
        } else {
            // If the screen is going to turn on because the caller explicitly requested it and
            // the keyguard is not showing don't attempt to sleep. Otherwise the Activity will
            // pause and then resume again later, which will result in a double life-cycle event.
            stack.checkReadyForSleep();
        }
    }

打印的日志:

09-02 17:27:17.227  3059  4340 I PowerManagerService: Waking up from dream (uid=1000 reason=android.server.am:TURN_ON:turnScreenOnFlag)...
09-02 17:27:17.230  3059  3084 I DreamManagerService: Gently waking up from dream.
09-02 17:27:17.231  3059  3080 I DreamManagerService: Performing gentle wake from dream.

 

你可能感兴趣的:(Android 启动Activity时唤醒系统的方法(Sleep、Dream))