今天有客户求助一个问题,说是之前在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.