启动系统特定功能的组合键的判断应该在系统分发按键消息前处理, 这样从系统运行
的角度来说成本最低。
添加组合键处理需要先搞清楚按键消息在framework中采集 和分发子系统的工作流程,
虽然有android自带的抓屏组合键处理可供参考, 但是理解这一流程还是很重要的,生
搬硬套可能会留下隐含的设计缺陷 。

Framework的按键预处理机制

framework中按键消息的接收和发送是在两个线程里实现的 。接收线程监听内核发送的
原始按键消息,通过轮训input/event节点实现, 接收线程将读取到的按键消息转换为
android系统定义的按键消息后添加到发送线程的消息队列里 ,发送线程再将消息分发
给android的视图系统,分发是一个比较复杂的过程, 和组合键处理无关这里不作分析 。

在接收线程添加消息之前和发送线程发送消息之前都会有一个回调给 framework做预处
理的。这种预处理机制就提供了系统处理组合按键的机会, 组合键的使用是策略相关
的,这两个预处理回调函数正是在framework/base/ policy/模块下的
PhoneWindowManager. java文件里面实现的。
两个接口如下:
public  int  interceptKeyBeforeQueueing( KeyEvent  event,  int  policyFlags,
boolean isScreenOn)
public  long interceptKeyBeforeDispatching( WindowState win, KeyEvent event,
int policyFlags)

组合键判断和处理流程

组合键无论用户怎么按,系统接收过程必定是串行的, 两个按键按下的间隔不能太
大,否则视为两个独立的按键;既然按键消息的串行接收的, 先来的按键消息就会被
添加到发送队列里面,这就要求发送前有一个确认机制, 如果组合键条件满足,则触
发对应功能,并取消发送。

预处理接口的处理流程简单描述:
接收预处理( interceptKeyBeforeQueueing):
记录组合键触发状态,触发时间,判断触发条件是否满足, 如果满足则启动快捷功
能,并标记按键消息被消费

发送预处理( interceptKeyBeforeDispatching) :
如果组合键触发时间没有溢出,则推迟发送;如果被消费, 则取消发送

组合键长按确认处理
如果组合按键需要长按确认,避免误操作?!,如长按‘ power’和‘volume-’启动抓屏
功能,则在判断触发条件满足后不是直接启动快捷功能, 而是发起一个延时启动请
求,如果延时请求发出前,按键抬起, 则取消正在等待的延时启动请求,并清除触发
标识。

在系统中增加组合键启动一个特定应用的设计方案实例:

Volume+和Volume-同时按下启动,不需要长按确认。

代码修改:

public class PhoneWindowManager implements WindowManagerPolicy {

private  boolean  mVolumeUpKeyTriggered;                   // 按键触发
(按下)标志
     private boolean mPowerKeyTriggered;
     private boolean mVolumeDownKeyTriggered;

+     private long mVolumeUpKeyTime;                          // 记录volume
键按下的时间
     private long mVolumeDownKeyTime;
     private long mPowerKeyTime;

+     private boolean mVolumeUpKeyConsumedByScreensh otChord;  // 标识volume
已经被系统消费
     // 变量名套用了android的抓屏功能原始设计, 实际上按键消费标识的判断使用
和消费对象无关
     private boolean mVolumeDownKeyConsumedByScreen shotChord;

// 组合键触发判断, 在接收预处理中调用
+    private void interceptQuickMemoChord() {
         // 音量键同时按下,并且电源键没有按下
+          if   (   mVolumeDownKeyTriggered   &&   !mPowerKeyTriggered   &&
mVolumeUpKeyTriggered) {
+            final long now = SystemClock.uptimeMillis();
+            try { // 查询要启动应用是否安装,如果应用没有安装直接返回
+                               mContext.getPackageManager(). getPackageInfo
("com.hisense.quickmemo",0);
+            } catch (NameNotFoundException e) {
+                Log.e(TAG, "no found com.hisense.quickmemo");
+                return;
+            }
+                   if       (now       <=       mVolumeDownKeyTime       +
SCREENSHOT_CHORD_DEBOUNCE_ DELAY_MILLIS
+                          &&      now      <=      mVolumeUpKeyTime      +
SCREENSHOT_CHORD_DEBOUNCE_ DELAY_MILLIS) {
+            // 按键触发事件在有效期内
+                mVolumeDownKeyConsumedByScreen shotChord = true;
+                mVolumeUpKeyConsumedByScreensh otChord = true;
+                mHandler.post( mQuickMemoChordPress);
/*    如果需要长按确认, 这里使用延时处理接口postDelayed, 指定一个长按确认时
间,并在按键up消息里面增加取消判断处理*/
+            }
+        }
+    }
+    // 启动快捷应用
+    private final Runnable mQuickMemoChordPress = new Runnable() {
+        public void run() {
+                       Log.d(TAG, "mQuickMemoChordLongPress");
+
+                       Intent intent = new Intent();
+                       intent.setFlags(Intent.FLAG_ ACTIVITY_NEW_TASK);
+                       intent.setAction("android. intent.action.MAIN");
+                       intent.setClassName("com. hisense.quickmemo",
+
"com.hisense.quickmemo. activities.QuickMemoActivity") ;
+                       mContext.startActivity(intent) ;
+        }
+    };
+
       // 发送预处理
@@   -1951,7   +2000,7   @@   public  class  PhoneWindowManager  implements
WindowManagerPolicy {
         if  (mScreenshotChordEnabled  &&  (flags & KeyEvent.FLAG_FALLBACK)
== 0) {
          // 推迟按键消息发送
+             if  ((mVolumeUpKeyTriggered  ||  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
                    && mVolumeDownKeyConsumedByScreen shotChord) {
                if (!down) {
                    mVolumeDownKeyConsumedByScreen shotChord = false;
                }
                return -1;
            }
+            if (keyCode == KeyEvent.KEYCODE_VOLUME_UP
+                    && mVolumeUpKeyConsumedByScreensh otChord) {
+                if (!down) {
+                    mVolumeUpKeyConsumedByScreensh otChord = false;
+                }
+                return -1;
+            }
         }

// 接收预处理
 @@   -3728,10  +3784,12  @@  public  class  PhoneWindowManager  implements
WindowManagerPolicy {
                if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
                    if (down) {
                        if (isScreenOn && !mVolumeDownKeyTriggered
                                &&            (event.getFlags()           &
KeyEvent.FLAG_FALLBACK) == 0) {
                            mVolumeDownKeyTriggered = true;
                            mVolumeDownKeyTime = event.getDownTime();
                             mVolumeDownKeyConsumedByScreen shotChord      =
false;
                             mVolumeDownKeyTime = event.getDownTime();
                             cancelPendingPowerKeyAction();
                             interceptScreenshotChord();
+                            interceptQuickMemoChord();
                         }
                     } else {
                         mVolumeDownKeyTriggered = false;
                         cancelPendingScreenshotChordAc tion();
                     }
                 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
                     if (down) {
@@   -3740,10   +3798,14  @@  public  class  PhoneWindowManager  implements
WindowManagerPolicy {
                             mVolumeUpKeyTriggered = true;
                             cancelPendingPowerKeyAction();
                             cancelPendingScreenshotChordAc tion();
+                            mVolumeUpKeyConsumedByScreensh otChord = false;
+                            mVolumeUpKeyTime = event.getDownTime();
+                            interceptQuickMemoChord();
                         }
                     } else {
                         mVolumeUpKeyTriggered = false;
                         cancelPendingScreenshotChordAc tion();
                     }
                 }
 (END)

在Android系统中添加组合键快捷启动功能相关推荐

  1. 在Android系统中添加一款新铃声

    想在Android系统中添加铃声,可以通过adb push 的方法,但如果要多次修改系统,每次push进去就显得太费劲了,这里有个简单的方法,就是把铃声编译进android 的system.img文件 ...

  2. android修改默认遥控器键值,RK3128平台android系统修改添加遥控器键值码值

    本帖最后由 微笑,一路向前 于 2017-1-4 15:34 编辑 最近帮客户定制RK3128平台的固件,涉及到定制新的遥控器,需要添加或修改遥控码值.RK3128平台Android系统修改遥控器码值 ...

  3. 向Android系统中添加模块及产品流程

     添加Android模块  一.基础知识: (1)在Android系统中,编译都是以模块(而不是文件)作为单位的,每个模块都有一个唯一的名称: (2)为了将模块编译到Android系统中,每个模块都需 ...

  4. android耳机上报流程,Android系统中耳机按键键值上报不正确 解决过程

    [问题现象] 根据测试组同事反馈:在我们的设备上使用 JBL 品牌某款带有 3 个按键的有线耳机时,按下"音量+"键时设备会减小音量而不是增加音量,按下"音量-" ...

  5. htc android sd卡,【HTC T328W】Android系统中SD卡各文件夹功能详解

    希望你的补充说明,让我们一起来清理内存卡吧注意,软件没有卸载前,不建议删除其文件荚!1..android_secure       是官方app2sd的产物,删了之后装到sd卡中的软件就无法使用了,小 ...

  6. Android系统中SD卡各文件夹功能详解

    1..android_secure  是官方app2sd的产物,删了之后装到sd卡中的软件就无法使用了. 2..Bluetooth  顾名思 义,用蓝牙之后就会有这个. 3..mobo  顾名思 义, ...

  7. android系统中sd卡各文件夹功能详解 guessword,AndroidStudio LiveTemplate函数说明

    1.annotated() 返回类.方法.属性的注解 例如:annotated("java.lang.Deprecated"),返回@Deprecated注解 2.arrayVar ...

  8. Android系统中如何添加USB网络共享

    Android系统中如何添加USB网络共享 类别 需求 索引类别 USB网络共享 问题描述 平台是RT1296,在Android系统中已经有支持USB网络共享,但相应的产品系统中还未开启USB网络共享 ...

  9. android属于数据库管理系统,详细谈谈Android系统中的SQLite数据库的应用

    数据库是按照数据结构来组织.存储和管理数据的仓库,而在信息话的社会,数据库又不单单仅限与数据的相关内容,现在数据库技术是管理信息系统.办公自动化系统.决策支持系统等各类信息系统的核心部分,而SQL是结 ...

最新文章

  1. GraphicsMagick扩展配置安装
  2. 极光推送配置(Android Studio),亲测有效
  3. 基于Web的质量和测试度量指标
  4. 注解配置声明式事务控制解析
  5. linux之vim/vi快速复制多行内容的快捷键
  6. P1407-[国家集训队]稳定婚姻【tarjan,强连通分量】
  7. textview 结束后释放_等待按键释放,你的代码如何写?
  8. 数据装载全/存量直接装载到目标表_09
  9. Exchange 日志/存储路径
  10. 【汇编语言与计算机系统结构笔记20】补充内容:可定制处理器指令集
  11. 判断非负整数是否是3的倍数_价格是最小变动价位(tick)整数倍检查
  12. origin游戏下载一直显示准备中的解决方法
  13. SAP OB53 本年利润科目的年初余额和年末余额不一致的伪问题
  14. Python+Flask(2)--通过flask paginate解决列表分页问题
  15. 祭出黑白共济战略,海信、TCL、创维、康佳能否打开增量消费市场?
  16. 解决远程连接服务器没有远程桌面授权服务器的许可证问题
  17. 河南省赛 导弹发射 lis
  18. 传真存储转发工作过程
  19. 备库ORA-00313 ORA-00312 ORA-27037
  20. Android系统学习(一)------编译系统Android7.0

热门文章

  1. 2008服务器做微信退款,Net微信退款开发流程
  2. 柯杰下赢机器人_柯洁再战人工智能 大胜“一秒识人机器人”
  3. 人工智能就业发展前景分析
  4. 盘点物联网架构的4个必要阶段
  5. OS2.2.4:FCFS、SJF、HRRN调度算法
  6. Python编程 元组中不允许的操作
  7. 怎么用计算机写材料,在ps中如何写字?ps文字工具使用教程 -电脑资料
  8. 如何在龙芯架构和国产化操作系统平台上运行javacv
  9. 51单片机(LED灯)
  10. 分享一个好用而且免费的GIF录制软件