本文的分析基于Android官方提供的Android7.0源码
Android设备长按电源键,会弹出一个对话框。
现有一个需求,就是定制一个弹出的对话框。
Android在Frameworks下的PhoneWindowManager对电源按键和Home键的事件做了处理,不会将这些键传送到上层应用。因此,我们可以从PhoneWindowManager入手处理长按电源键的一系列事件。
PhoneWindowManager的源码路径:
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
PhoneWindowManager这个类的源码有近8000行,我们不需要从头到尾分析它。我们在源码中搜索关键字:KeyEvent.KEYCODE_POWER,发现该关键字出在“interceptKeyBeforeQueueing”方法里,这方法大概在PhoneWindowManager的5542行,从方法名大概可以猜出该方法就是在系统将事件放到队列之前进行拦截。我们看看KeyEvent.KEYCODE_POWER相关的代码:
case KeyEvent.KEYCODE_POWER: {
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false; // wake-up will be handled separately
if (down) {
interceptPowerKeyDown(event, interactive);
} else {
interceptPowerKeyUp(event, interactive, canceled);
}
break;
}
再看看” interceptPowerKeyDown”这个方法:该方法大概100行,处理了各种情况下按下电源按键的事件,就不便贴出全部代码。在该方法的末尾,我发现了跟长按事件有关的代码片段:
private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
//省略代码……
// If the power key has still not yet been handled, then detect short
// press, long press, or multi press and decide what to do.
mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
|| mScreenshotChordVolumeUpKeyTriggered || gesturedServiceIntercepted;
if (!mPowerKeyHandled) {
if (interactive) {
// When interactive, we're already awake.
// Wait for a long press or for the button to be released to decide what to do.
if (hasLongPressOnPowerBehavior()) {
Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg,
//省略代码……
}
} else {
//省略代码……
Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg,
ViewConfiguration.get(mContext).getDeviceG