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

简介:

      Step 36. ViewRoot.finishInputEvent

         这个函数定义在frameworks/base/core/java/android/view/ViewRoot.java文件中:

  1. public final class ViewRoot extends Handler implements ViewParent,  
  2.         View.AttachInfo.Callbacks {  
  3.     ......  
  4.   
  5.     private void finishInputEvent() {  
  6.         ......  
  7.   
  8.         if (mFinishedCallback != null) {  
  9.             mFinishedCallback.run();  
  10.             mFinishedCallback = null;  
  11.         } else {  
  12.             ......  
  13.         }  
  14.     }  
  15.   
  16.     ......  
  17. }  

         ViewRoot类里面的成员变量mFinishedCallback是在前面Step 25中由InputQueue设置的,它是一个Runnable对象,实际类型是定义在InputQueue的内部类FinishedCallback,因此,这里调用它的run方法时,接下来就会调用InputQueue的内部类FinishedCallback的run成员函数:

  1. public final class InputQueue {  
  2.     ......  
  3.   
  4.     private static class FinishedCallback implements Runnable {  
  5.         ......  
  6.   
  7.         public void run() {  
  8.             synchronized (sLock) {  
  9.                 ......  
  10.   
  11.                 nativeFinished(mFinishedToken);  
  12.                   
  13.                 ......  
  14.             }  
  15.         }  
  16.   
  17.         ......  
  18.     }  
  19.   
  20.     ......  
  21. }  

        这里它调用外部类InputQueue的本地方法nativeFinished来进一步处理。

       Step 37.  InputQueue.nativeFinished

        这个函数定义在frameworks/base/core/jni/android_view_InputQueue.cpp文件中:

  1. static void android_view_InputQueue_nativeFinished(JNIEnv* env, jclass clazz,  
  2.         jlong finishedToken) {  
  3.     status_t status = gNativeInputQueue.finished(  
  4.         env, finishedToken, false /*ignoreSpuriousFinish*/);  
  5.   
  6.     ......  
  7. }  
        这个函数只是简单只调用NativeInputQueue的finished方法来进一处处理。

 

        Step 38. NativeInputQueue.finished

        这个函数定义在frameworks/base/core/jni/android_view_InputQueue.cpp文件中:

  1. status_t NativeInputQueue::finished(JNIEnv* env, jlong finishedToken, bool ignoreSpuriousFinish) {  
  2.     int32_t receiveFd;  
  3.     uint16_t connectionId;  
  4.     uint16_t messageSeqNum;  
  5.     parseFinishedToken(finishedToken, &receiveFd, &connectionId, &messageSeqNum);  
  6.   
  7.     { // acquire lock  
  8.         AutoMutex _l(mLock);  
  9.   
  10.         ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(receiveFd);  
  11.         ......  
  12.   
  13.         sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);  
  14.         ......  
  15.   
  16.         connection->messageInProgress = false;  
  17.   
  18.         status_t status = connection->inputConsumer.sendFinishedSignal();  
  19.           
  20.         ......  
  21.     } // release lock  
  22.   
  23.     return OK;  
  24. }  
        这个函数最重要的参数便是finishedToken了,通过它可以获得之前通知Java层的InputQueue类来处理键盘事件的Connection对象,它的值是在上面的Step 21(NativeInputQueue.handleReceiveCallback)中生成的:

  1. finishedToken = generateFinishedToken(receiveFd, connection->id, connection->messageSeqNum);  

        函数generateFinishedToken的定义如下:

  1. jlong NativeInputQueue::generateFinishedToken(int32_t receiveFd, uint16_t connectionId,  
  2.         uint16_t messageSeqNum) {  
  3.     return (jlong(receiveFd) << 32) | (jlong(connectionId) << 16) | jlong(messageSeqNum);  
  4. }  

        它的实现很简单,只是把receiveFd(前向管道的读端文件描述符)、connectionId(Client端的InputChannel对应的Connection对象在NativeInputQueue中的索引)和messageSeqNum(键盘消息的序列号)三个数值通过移位的方式编码在一个jlong值里面,即编码在上面的finishedToken参数里面。

 

        因此,在上面的finished函数里面,首先就是要对参数值finishedToken进行解码,把receiveFd、connectionId和messageSeqNum三个值分别取回来:

  1. parseFinishedToken(finishedToken, &receiveFd, &connectionId, &messageSeqNum);  

       parseFinishedToken的定义如下:

  1. void NativeInputQueue::parseFinishedToken(jlong finishedToken,  
  2.         int32_t* outReceiveFd, uint16_t* outConnectionId, uint16_t* outMessageIndex) {  
  3.     *outReceiveFd = int32_t(finishedToken >> 32);  
  4.     *outConnectionId = uint16_t(finishedToken >> 16);  
  5.     *outMessageIndex = uint16_t(finishedToken);  
  6. }  

       有了这个receiveFd和connectionId之后,就可以把相应的Connection对象取回来了:

  1. ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(receiveFd);  
  2.         ......  
  3.   
  4. sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);  

       接下来就是调用这个connection对象中的inputConsumer对象来发送信号通知Server端的InputChannel,应用程序这一侧处理完刚才发生的键盘事件了:

  1. status_t status = connection->inputConsumer.sendFinishedSignal();  




本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966645,如需转载请自行联系原作者
目录
相关文章
|
9月前
|
存储 Android开发
如何查看Flutter应用在Android设备上已被撤销的权限?
如何查看Flutter应用在Android设备上已被撤销的权限?
384 64
|
4月前
|
存储 消息中间件 人工智能
【08】AI辅助编程完整的安卓二次商业实战-修改消息聊天框背景色-触发聊天让程序异常终止bug牵涉更多聊天消息发送优化处理-优雅草卓伊凡
【08】AI辅助编程完整的安卓二次商业实战-修改消息聊天框背景色-触发聊天让程序异常终止bug牵涉更多聊天消息发送优化处理-优雅草卓伊凡
320 10
【08】AI辅助编程完整的安卓二次商业实战-修改消息聊天框背景色-触发聊天让程序异常终止bug牵涉更多聊天消息发送优化处理-优雅草卓伊凡
|
9月前
|
存储 Android开发 数据安全/隐私保护
如何在Android设备上撤销Flutter应用程序的所有权限?
如何在Android设备上撤销Flutter应用程序的所有权限?
508 64
|
9月前
|
缓存 Android开发 开发者
Flutter环境配置完成后,如何在Android设备上运行Flutter应用程序?
Flutter环境配置完成后,如何在Android设备上运行Flutter应用程序?
1552 62
|
9月前
|
开发工具 Android开发 开发者
在Android设备上运行Flutter应用程序时,如果遇到设备未授权的问题该如何解决?
在Android设备上运行Flutter应用程序时,如果遇到设备未授权的问题该如何解决?
550 61
|
11月前
|
前端开发 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
727 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
11月前
|
Dart 前端开发 Android开发
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
356 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
328 14
|
搜索推荐 前端开发 测试技术
打造个性化安卓应用:从设计到开发的全面指南
在这个数字时代,拥有一个定制的移动应用不仅是一种趋势,更是个人或企业品牌的重要延伸。本文将引导你通过一系列简单易懂的步骤,从构思你的应用理念开始,直至实现一个功能齐全的安卓应用。无论你是编程新手还是希望拓展技能的开发者,这篇文章都将为你提供必要的工具和知识,帮助你将创意转化为现实。
|
Java Maven Android开发
Android自定义一个车牌字母选择键盘
和省份简称键盘不同的是,数据源上和边距有所差别之外,其他的实现方式均是一样的,采用外部垂直LinearLayout,内部多个横向的LinearLayout的搭配方式。
316 0

热门文章

最新文章