Power长按、组合键分析
来源:互联网 发布:休格兰特 知乎 编辑:程序博客网 时间:2024/06/14 09:42
1.Power长按功能原理
当按下power时
- Log.i(TAG, "PowerKey down, isScreenOn = " + isScreenOn);
- interceptPowerKeyDown(!isScreenOn || hungUp
- || mVolumeDownKeyTriggered || mVolumeUpKeyTriggered);
Log.i(TAG, "PowerKey down, isScreenOn = " + isScreenOn); interceptPowerKeyDown(!isScreenOn || hungUp || mVolumeDownKeyTriggered || mVolumeUpKeyTriggered);
- private void interceptPowerKeyDown(boolean handled) {
- mPowerKeyHandled = handled;
- if (!handled || mChangeLongPressPowerKey) {
- if(mChangeLongPressPowerKey) {
- Log.d(TAG,"fast boot acquire cpu wakelock for timeout :"+(ViewConfiguration.getGlobalActionKeyTimeout()+100));
- PowerManager.WakeLock fastBootWake = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "FastBootWake");
- fastBootWake.acquire(ViewConfiguration.getGlobalActionKeyTimeout()+100);
- }
- mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout());
- }
- }
private void interceptPowerKeyDown(boolean handled) { mPowerKeyHandled = handled; if (!handled || mChangeLongPressPowerKey) { if(mChangeLongPressPowerKey) { Log.d(TAG,"fast boot acquire cpu wakelock for timeout :"+(ViewConfiguration.getGlobalActionKeyTimeout()+100)); PowerManager.WakeLock fastBootWake = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "FastBootWake"); fastBootWake.acquire(ViewConfiguration.getGlobalActionKeyTimeout()+100); } mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout()); } }
抬起手时
- Log.i(TAG, "PowerKey up");
- mPowerKeyTriggered = false;
- cancelPendingScreenshotChordAction();
- if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {
- result = (result & ~ACTION_WAKE_UP) | ACTION_GO_TO_SLEEP;
- }
- mPendingPowerKeyUpCanceled = false;
Log.i(TAG, "PowerKey up"); mPowerKeyTriggered = false; cancelPendingScreenshotChordAction(); if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) { result = (result & ~ACTION_WAKE_UP) | ACTION_GO_TO_SLEEP; } mPendingPowerKeyUpCanceled = false;
- private boolean interceptPowerKeyUp(boolean canceled) {
- if (!mPowerKeyHandled) {
- mHandler.removeCallbacks(mPowerLongPress);
- return !canceled;
- }
- if (mChangeLongPressPowerKey) {
- mHandler.removeCallbacks(mPowerLongPress);
- }
- return false;
- }
private boolean interceptPowerKeyUp(boolean canceled) { if (!mPowerKeyHandled) { mHandler.removeCallbacks(mPowerLongPress); return !canceled; } if (mChangeLongPressPowerKey) { mHandler.removeCallbacks(mPowerLongPress); } return false; }
根据以上代码分析知,在亮屏、音量键没触发、power键没进行挂电话行为时,按下power会进入mPowerLongPress启动的倒计时,当抬起手时会判断power键的事件是否被消耗,如果没被消耗则移除mPowerLongPress事件,并返回传进来的boolean的相反值。
mPendingPowerKeyUpCanceled的值控制如下
- private void cancelPendingPowerKeyAction() {
- if (!mPowerKeyHandled) {
- mHandler.removeCallbacks(mPowerLongPress);
- }
- if (mPowerKeyTriggered) {
- mPendingPowerKeyUpCanceled = true;
- }
- }
private void cancelPendingPowerKeyAction() { if (!mPowerKeyHandled) { mHandler.removeCallbacks(mPowerLongPress); } if (mPowerKeyTriggered) { mPendingPowerKeyUpCanceled = true; } }
总结来说:要想实现长按,需要1.一个boolean值用于判断按下的事件是否消费,如mPowerKeyHandled。2.handler延迟执行长按的事件,并且在长按事件的执行代码中把事件boolean设置为消费状态。3.up事件中判断这次按下事件是否被消耗,如果没则处理单点流程。
长按实现:记录下第一次按下的时间,记录此次事件是否被消费,在down事件中判断是否达到了长按时间,在up事件中把事件归零并判断事件是否消费并重置。
2.组合键原理
长按power+音量下可以截图,以此为例分析
在power键的down事件中有如下代码
- if (isScreenOn && !mPowerKeyTriggered
- && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
- mPowerKeyTriggered = true;
- mPowerKeyTime = event.getDownTime();
- interceptScreenshotChord();
- }
if (isScreenOn && !mPowerKeyTriggered && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { mPowerKeyTriggered = true; mPowerKeyTime = event.getDownTime(); interceptScreenshotChord(); }
- private void interceptScreenshotChord() {
- if (mScreenshotChordEnabled
- && mVolumeDownKeyTriggered && mPowerKeyTriggered && !mVolumeUpKeyTriggered) {
- final long now = SystemClock.uptimeMillis();
- if (now <= mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
- && now <= mPowerKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
- mVolumeDownKeyConsumedByScreenshotChord = true;
- cancelPendingPowerKeyAction();
- mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());
- }
- }
- }
private void interceptScreenshotChord() { if (mScreenshotChordEnabled && mVolumeDownKeyTriggered && mPowerKeyTriggered && !mVolumeUpKeyTriggered) { final long now = SystemClock.uptimeMillis(); if (now <= mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS && now <= mPowerKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) { mVolumeDownKeyConsumedByScreenshotChord = true; cancelPendingPowerKeyAction(); mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay()); } } }
音量-按键down事件
- if (isScreenOn && !mVolumeDownKeyTriggered
- && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
- mVolumeDownKeyTriggered = true;
- mVolumeDownKeyTime = event.getDownTime();
- mVolumeDownKeyConsumedByScreenshotChord = false;
- cancelPendingPowerKeyAction();
- interceptScreenshotChord();
- }
if (isScreenOn && !mVolumeDownKeyTriggered && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { mVolumeDownKeyTriggered = true; mVolumeDownKeyTime = event.getDownTime(); mVolumeDownKeyConsumedByScreenshotChord = false; cancelPendingPowerKeyAction(); interceptScreenshotChord(); }根据以上代码可以分析出;power键按下时记下按下的时间并且mPowerKeyTriggered设为true,音量键同样如此,两个都调用了interceptScreenshotChord()方法,也就是说先按下哪个键不影响。在interceptScreenshotChord()方法中,如果power被触发、音量down被触发,音量up没被触发则继续判断两个按键按下的间隔是否在一定时间内,如果是则开始进入截屏流程,并把mVolumeDownKeyConsumedByScreenshotChord设为true,mVolumeDownKeyConsumedByScreenshotChord值用于阻止音量按键事件往下传递用,在interceptKeyBeforeDispatching方法内
- if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
- if (mVolumeDownKeyTriggered && !mPowerKeyTriggered) {
- final long now = SystemClock.uptimeMillis();
- final long timeoutTime = mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
- if (now < timeoutTime) {
- return timeoutTime - now;
- }
- }
- if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
- && mVolumeDownKeyConsumedByScreenshotChord) {
- if (!down) {
- mVolumeDownKeyConsumedByScreenshotChord = false;
- }
- return -1;
- }
- }
if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) { if (mVolumeDownKeyTriggered && !mPowerKeyTriggered) { final long now = SystemClock.uptimeMillis(); final long timeoutTime = mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS; if (now < timeoutTime) { return timeoutTime - now; } } if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN && mVolumeDownKeyConsumedByScreenshotChord) { if (!down) { mVolumeDownKeyConsumedByScreenshotChord = false; } return -1; } }可以看出,如果先按的是音量-键,那么在一定时间内事件是没有被传递下去,当抬手时则mVolumeDownKeyConsumedByScreenshotChord=true.不过mVolumeDownKeyConsumedByScreenshotChord好像没什么用。
总结:要想实现组合键,1、记录两个按键的按下时间。2、记录两个按键是否按下触发。3、每个按键按下时触发同一个方法并在此方法内判读两个按键按下的时间差是否在一定时间内,如果是则组合按键生效。
注意:power按键之所以在组合按键起效时不响应点击或者长按事件,因为处理时判断了音量键是否按下去了,如果按下了则不起效。而如果power键先按,则在音量键按下时调用了mVolumeDownKeyConsumedByScreenshotChord
- private void cancelPendingPowerKeyAction() {
- if (!mPowerKeyHandled) {
- mHandler.removeCallbacks(mPowerLongPress);
- }
- if (mPowerKeyTriggered) {
- mPendingPowerKeyUpCanceled = true;
- }
- }
private void cancelPendingPowerKeyAction() { if (!mPowerKeyHandled) { mHandler.removeCallbacks(mPowerLongPress); } if (mPowerKeyTriggered) { mPendingPowerKeyUpCanceled = true; } }mPendingPowerKeyUpCanceled的用途是阻止power松开时灭屏
阅读全文
0 0
- Power长按、组合键分析
- Power长按、组合键分析
- Android 5.1 长按power键流程分析
- 长按power key的流程分析
- android长按power键自动关机定制
- Android4.2 长按POWER键休眠
- 捕捉Power键的长按与短按处理
- 捕捉Power键的长按与短按处理
- 如何做到长按power键唤醒系统!
- [Android]长按电源键(Power Key)的处理
- 长按Power键关机从Framework到Kernel
- Android源码开发之长按power键添加GlobalActions
- 长按Power键默认会弹出对话框
- SetupWizard界面长按Power键没有飞行模式选项
- android4.2 长按POWER键3秒关机
- Android 5.1 截屏事件分析(Power + VolumeDown)组合键分析
- Android长按Power键弹出关机Dialog框GlobalActions解析
- Android长按Power键弹出关机Dialog框GlobalActions解析
- Android NDK开发扫盲及最新CMake的编译使用
- jquery 中 layer的用法
- Iptables与Firewalld防火墙
- instanceof
- 关于双向链表的操作详解
- Power长按、组合键分析
- Android 整个手机屏幕截图和去除状态栏截图
- MVC模式
- java&javaScript常见校验器
- 区域生长
- PHP计算两个经纬度之间的距离
- 【Java面试】Java 多线程入门学习
- SylixOS 双网卡冗余备份使用说明
- MYSQL数据库 初学笔记3-SELECT