ANDROID8.0 雙擊POWER鍵啟動(dòng)流程及音量面板調(diào)取需求實(shí)現(xiàn)
標(biāo)簽: Android 雙擊power鍵啟動(dòng)流程 雙擊power鍵 Android啟動(dòng)音量面板 Android power鍵
之前參考雙擊調(diào)用Camera,添加了一個(gè)雙擊啟動(dòng)音量面板的功能,為啥?因?yàn)檫@手機(jī)只有power鍵!
實(shí)現(xiàn)功能前,先摸清流程對我們的開發(fā)會(huì)更方便。
POWER鍵大概流程

PhoneWindowManager.java 類是 處理各種 power 鍵流程的地方,
case KeyEvent.KEYCODE_POWER:
if (down) {
interceptPowerKeyDown(event, interactive);
} else {
interceptPowerKeyUp(event, interactive, canceled);
}
power鍵按下在interceptPowerKeyDown()執(zhí)行,松開的操作在interceptPowerKeyUp()中執(zhí)行
interceptPowerKeyDown()方法中會(huì)調(diào)用 GestureLauncherService.java 的 interceptPowerKeyDown() 方法
GestureLauncherService gestureService = LocalServices.getService(
GestureLauncherService.class);
boolean gesturedServiceIntercepted = false;
if (gestureService != null) {
gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive,
mTmpBoolean);
if (mTmpBoolean.value && mRequestedOrGoingToSleep) {
mCameraGestureTriggeredDuringGoingToSleep = true;
}
}
跟蹤看看GestureLauncherService.java 中 執(zhí)行 interceptPowerKeyDown()方法如下
public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive,
MutableBoolean outLaunched) {
boolean launched = false;
boolean intercept = false;
long powerTapInterval;
synchronized (this) {
powerTapInterval = event.getEventTime() - mLastPowerDown;
if (mCameraDoubleTapPowerEnabled
&& powerTapInterval < CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS) {//雙擊事件
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DOUBLE_TAP_TAG,1);
launched = true;
intercept = interactive;
mPowerButtonConsecutiveTaps++;
} else if (powerTapInterval < POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS) {//延遲雙擊事件
mPowerButtonConsecutiveTaps++;
} else {//單擊事件
mPowerButtonConsecutiveTaps = 1;
}
mLastPowerDown = event.getEventTime();
}
if (DBG && mPowerButtonConsecutiveTaps > 1) {
Slog.i(TAG, Long.valueOf(mPowerButtonConsecutiveTaps) +
" consecutive power button taps detected");
}
if (launched) {
Slog.i(TAG, "Power button double tap gesture detected, launching camera. Interval="
+ powerTapInterval + "ms");
//調(diào)用開啟相機(jī)
launched = handleCameraGesture(false/* useWakelock */,
StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP);
if (launched) {
mMetricsLogger.action(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE,
(int) powerTapInterval);
}
}
mMetricsLogger.histogram("power_consecutive_short_tap_count", mPowerButtonConsecutiveTaps);
mMetricsLogger.histogram("power_double_tap_interval", (int) powerTapInterval);
outLaunched.value = launched;
return intercept && launched;
}
系統(tǒng)會(huì)對mCameraDoubleTapPowerEnabled 取值,核心是通過resources.getBoolean(com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled) 來取,
其實(shí)這個(gè)值是配置在/frameworks/base/core/res/res/values/config.xml中,這里是為true的
<!-- Allow the gesture to double tap the power button twice to start the camera while the deviceis non-interactive. -->
<bool name="config_cameraDoubleTapPowerGestureEnabled">true</bool>12
接下來會(huì)分別對power連續(xù)按2或者1次進(jìn)行判斷,如果mCameraDoubleTapPowerEnabled = true 會(huì)通過比較按鍵的時(shí)間powerTapInterval小于系統(tǒng)默認(rèn)時(shí)間(CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS=300毫秒),
mPowerButtonConsecutiveTaps計(jì)數(shù)加1,說明連續(xù)按power鍵,或者延遲最大500毫秒內(nèi)連續(xù)按鍵,系統(tǒng)預(yù)計(jì)用戶接下來可能會(huì)執(zhí)行一些操作,計(jì)數(shù)也會(huì)加1.
static final long POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS = 500;
static final long CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS = 300;
powerTapInterval = event.getEventTime() - mLastPowerDown;
mLastPowerDown = event.getEventTime();
if (mCameraDoubleTapPowerEnabled && powerTapInterval < CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS)
if (powerTapInterval < POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS)
執(zhí)行完成之后會(huì)調(diào)用 handleCameraGesture()方法調(diào)用開啟攝像機(jī)。
@VisibleForTesting
boolean handleCameraGesture(boolean useWakelock, int source) {
boolean userSetupComplete = Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
if (!userSetupComplete) {
if (DBG) Slog.d(TAG, String.format(
"userSetupComplete = %s, ignoring camera gesture.",
userSetupComplete));
return false;
}
if (DBG) Slog.d(TAG, String.format(
"userSetupComplete = %s, performing camera gesture.",
userSetupComplete));
if (useWakelock) {
// Make sure we don't sleep too early
mWakeLock.acquire(500L);
}
StatusBarManagerInternal service = LocalServices.getService(
StatusBarManagerInternal.class);
//啟動(dòng)相機(jī)
service.onCameraLaunchGestureDetected(source);
return true;
}
原生雙擊啟動(dòng)相機(jī)流程差不多是這樣,后面service不詳細(xì)說,但是我們這里是需要啟動(dòng)音量面板啊~
需求實(shí)現(xiàn)
流程縷清了實(shí)現(xiàn)起來就很方便了,現(xiàn)在雙擊事件那邊記錄下一個(gè)標(biāo)記值
if (mCameraDoubleTapPowerEnabled&& powerTapInterval < CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS) {
//雙擊事件,添加標(biāo)記為1
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DOUBLE_TAP_TAG,1);
然后在外層 PhoneWindowManager.java 添加如果在setting那邊選了調(diào)用音量面板模式和雙擊標(biāo)記值符合則調(diào)用音量面板顯示即可完成需求。
case KeyEvent.KEYCODE_POWER: {
final int powerKeyModeTag = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, 0);
int doubleTapTag = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.DOUBLE_TAP_TAG, 0);
mCameraDoubleTapPowerEnabled = powerKeyModeTag == 2 ? true : false;
mButtonDoubleTapPowerEnabled = doubleTapTag == 1 ? true : false;
if (mCameraDoubleTapPowerEnabled
&& mButtonDoubleTapPowerEnabled) {
AudioManager am = (AudioManager)mContext. getSystemService(mContext.AUDIO_SERVICE);
am.adjustVolume(AudioManager.ADJUST_SAME, AudioManager.FLAG_SHOW_UI) ;
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DOUBLE_TAP_TAG,0);
return ACTION_PASS_TO_USER;
}
...
break;
}
如果大家有更好的辦法歡迎指導(dǎo)交流~~
版權(quán)聲明:本文為ouzhuangzhuang原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接和本聲明。
本文鏈接:https://blog.csdn.net/ouzhuangzhuang/article/details/82150180