Android应用程序键盘(Keyboard)消息处理机制分析(15)

简介:

     Step 7. KeyboardInputMapper.processKey

 

        这个函数定义在frameworks/base/libs/ui/InputReader.cpp文件中:

  1. void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,  
  2.         int32_t scanCode, uint32_t policyFlags) {  
  3.     int32_t newMetaState;  
  4.     nsecs_t downTime;  
  5.     bool metaStateChanged = false;  
  6.   
  7.     { // acquire lock  
  8.      AutoMutex _l(mLock);  
  9.   
  10.      if (down) {  
  11.          // Rotate key codes according to orientation if needed.  
  12.          // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.  
  13.          if (mAssociatedDisplayId >= 0) {  
  14.              int32_t orientation;  
  15.              if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {  
  16.                  return;  
  17.              }  
  18.   
  19.              keyCode = rotateKeyCode(keyCode, orientation);  
  20.          }  
  21.   
  22.          // Add key down.  
  23.          ssize_t keyDownIndex = findKeyDownLocked(scanCode);  
  24.          if (keyDownIndex >= 0) {  
  25.              // key repeat, be sure to use same keycode as before in case of rotation  
  26.              keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;  
  27.          } else {  
  28.              // key down  
  29.              if ((policyFlags & POLICY_FLAG_VIRTUAL)  
  30.                  && mContext->shouldDropVirtualKey(when, getDevice(), keyCode, scanCode)) {  
  31.                      return;  
  32.              }  
  33.              mLocked.keyDowns.push();  
  34.              KeyDown& keyDown = mLocked.keyDowns.editTop();  
  35.              keyDown.keyCode = keyCode;  
  36.              keyDown.scanCode = scanCode;  
  37.          }  
  38.   
  39.          mLocked.downTime = when;  
  40.      } else {  
  41.          // Remove key down.  
  42.          ssize_t keyDownIndex = findKeyDownLocked(scanCode);  
  43.          if (keyDownIndex >= 0) {  
  44.              // key up, be sure to use same keycode as before in case of rotation  
  45.              keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;  
  46.              mLocked.keyDowns.removeAt(size_t(keyDownIndex));  
  47.          } else {  
  48.              // key was not actually down  
  49.              LOGI("Dropping key up from device %s because the key was not down.  "  
  50.                  "keyCode=%d, scanCode=%d",  
  51.                  getDeviceName().string(), keyCode, scanCode);  
  52.              return;  
  53.          }  
  54.      }  
  55.   
  56.      int32_t oldMetaState = mLocked.metaState;  
  57.      newMetaState = updateMetaState(keyCode, down, oldMetaState);  
  58.      if (oldMetaState != newMetaState) {  
  59.          mLocked.metaState = newMetaState;  
  60.          metaStateChanged = true;  
  61.      }  
  62.   
  63.      downTime = mLocked.downTime;  
  64.     } // release lock  
  65.   
  66.   
  67.     if (metaStateChanged) {  
  68.         getContext()->updateGlobalMetaState();  
  69.     }  
  70.   
  71.     getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,  
  72.         down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,  
  73.         AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);  
  74. }  

        这个函数首先对对按键作一些处理,例如,当某一个DPAD键被按下时,根据当时屏幕方向的不同,它所表示的意义也不同,因此,这里需要根据当时屏幕的方向来调整键盘码:

 

  1. // Rotate key codes according to orientation if needed.  
  2. // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.  
  3. if (mAssociatedDisplayId >= 0) {  
  4.     int32_t orientation;  
  5.     if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {  
  6.         return;  
  7.     }  
  8.   
  9.     keyCode = rotateKeyCode(keyCode, orientation);  
  10. }  

        如果这个键是一直按着不放的,不管屏幕的方向如何,必须保证后面的键盘码和前面的一样:

  1. // Add key down.  
  2. ssize_t keyDownIndex = findKeyDownLocked(scanCode);  
  3. if (keyDownIndex >= 0) {  
  4.     // key repeat, be sure to use same keycode as before in case of rotation  
  5.     keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;  
  6. else {  
  7.     // key down  
  8.     if ((policyFlags & POLICY_FLAG_VIRTUAL)  
  9.         && mContext->shouldDropVirtualKey(when, getDevice(), keyCode, scanCode)) {  
  10.          return;  
  11.     }  
  12.     mLocked.keyDowns.push();  
  13.     KeyDown& keyDown = mLocked.keyDowns.editTop();  
  14.     keyDown.keyCode = keyCode;  
  15.     keyDown.scanCode = scanCode;  
  16. }  

       如果是第一次按下某个键,还必须把它保存在mLocked.keyDowns里面,就是为了处理上面讲的当这个键盘一直按着不放的时候屏幕方向发生改变的情况。
       如果是松开键盘上的某个键,就把它从mLocked.keyDowns里面删除:

  1. // Remove key down.  
  2. ssize_t keyDownIndex = findKeyDownLocked(scanCode);  
  3. if (keyDownIndex >= 0) {  
  4.     // key up, be sure to use same keycode as before in case of rotation  
  5.     keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;  
  6.     mLocked.keyDowns.removeAt(size_t(keyDownIndex));  
  7. else {  
  8.     // key was not actually down  
  9.     LOGI("Dropping key up from device %s because the key was not down.  "  
  10.         "keyCode=%d, scanCode=%d",  
  11.         getDeviceName().string(), keyCode, scanCode);  
  12.     return;  
  13. }  

        当然,对键盘事件的这些处理不是本文的重点,本文的重点是分析从键盘事件到当前激活的Activity窗口接收到这个键盘消息的过程。

 

        最后,KeyboardInputMappger函数通知InputDispatcher,有键盘事件发生了:

  1. getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,  
  2.     down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,  
  3.     AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);  




本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966633,如需转载请自行联系原作者
目录
相关文章
|
存储 Android开发
如何查看Flutter应用在Android设备上已被撤销的权限?
如何查看Flutter应用在Android设备上已被撤销的权限?
649 64
|
存储 Android开发 数据安全/隐私保护
如何在Android设备上撤销Flutter应用程序的所有权限?
如何在Android设备上撤销Flutter应用程序的所有权限?
838 64
|
缓存 Android开发 开发者
Flutter环境配置完成后,如何在Android设备上运行Flutter应用程序?
Flutter环境配置完成后,如何在Android设备上运行Flutter应用程序?
2381 62
|
开发工具 Android开发 开发者
在Android设备上运行Flutter应用程序时,如果遇到设备未授权的问题该如何解决?
在Android设备上运行Flutter应用程序时,如果遇到设备未授权的问题该如何解决?
913 61
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
921 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
11月前
|
消息中间件 Android开发
Android Handler的使用方式以及其机制的简单介绍
Handler 是 Android 中实现线程间通信的重要机制,可传递任意两线程数据。常用场景包括子线程向主线程(UI 线程)传递结果,以及主线程向子线程发送消息。其核心涉及四个类:Handler(发送/接收消息)、Message(消息载体)、MessageQueue(消息队列)和 Looper(消息循环泵)。基本流程为:Handler 发送 Message 至 MessageQueue,Looper 从队列中按 FIFO 取出并处理。
352 0
|
Dart 前端开发 Android开发
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
471 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
402 14
|
搜索推荐 前端开发 测试技术
打造个性化安卓应用:从设计到开发的全面指南
在这个数字时代,拥有一个定制的移动应用不仅是一种趋势,更是个人或企业品牌的重要延伸。本文将引导你通过一系列简单易懂的步骤,从构思你的应用理念开始,直至实现一个功能齐全的安卓应用。无论你是编程新手还是希望拓展技能的开发者,这篇文章都将为你提供必要的工具和知识,帮助你将创意转化为现实。
|
Java Android开发 开发者
探索安卓开发:构建你的第一个“Hello World”应用
在安卓开发的浩瀚海洋中,每个新手都渴望扬帆起航。本文将作为你的指南针,引领你通过创建一个简单的“Hello World”应用,迈出安卓开发的第一步。我们将一起搭建开发环境、了解基本概念,并编写第一行代码。就像印度圣雄甘地所说:“你必须成为你希望在世界上看到的改变。”让我们一起开始这段旅程,成为我们想要见到的开发者吧!
339 0

热门文章

最新文章