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,如需转载请自行联系原作者
目录
相关文章
|
2月前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
264 4
|
2月前
|
安全 Android开发 数据安全/隐私保护
深入探讨iOS与Android系统安全性对比分析
在移动操作系统领域,iOS和Android无疑是两大巨头。本文从技术角度出发,对这两个系统的架构、安全机制以及用户隐私保护等方面进行了详细的比较分析。通过深入探讨,我们旨在揭示两个系统在安全性方面的差异,并为用户提供一些实用的安全建议。
|
1月前
|
Java 开发工具 Android开发
安卓与iOS开发环境对比分析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自占据半壁江山。本文深入探讨了这两个平台的开发环境,从编程语言、开发工具到用户界面设计等多个角度进行比较。通过实际案例分析和代码示例,我们旨在为开发者提供一个清晰的指南,帮助他们根据项目需求和个人偏好做出明智的选择。无论你是初涉移动开发领域的新手,还是寻求跨平台解决方案的资深开发者,这篇文章都将为你提供宝贵的信息和启示。
36 8
|
3月前
|
缓存 Java Shell
Android 系统缓存扫描与清理方法分析
Android 系统缓存从原理探索到实现。
105 15
Android 系统缓存扫描与清理方法分析
|
2月前
|
安全 Android开发 数据安全/隐私保护
深入探索Android与iOS系统安全性的对比分析
在当今数字化时代,移动操作系统的安全已成为用户和开发者共同关注的重点。本文旨在通过比较Android与iOS两大主流操作系统在安全性方面的差异,揭示两者在设计理念、权限管理、应用审核机制等方面的不同之处。我们将探讨这些差异如何影响用户的安全体验以及可能带来的风险。
62 1
|
3月前
|
Java API Android开发
安卓应用程序开发的新手指南:从零开始构建你的第一个应用
【10月更文挑战第20天】在这个数字技术不断进步的时代,掌握移动应用开发技能无疑打开了一扇通往创新世界的大门。对于初学者来说,了解并学习如何从无到有构建一个安卓应用是至关重要的第一步。本文将为你提供一份详尽的入门指南,帮助你理解安卓开发的基础知识,并通过实际示例引导你完成第一个简单的应用项目。无论你是编程新手还是希望扩展你的技能集,这份指南都将是你宝贵的资源。
123 5
|
3月前
|
开发工具 Android开发 Swift
安卓与iOS开发环境的差异性分析
【10月更文挑战第8天】 本文旨在探讨Android和iOS两大移动操作系统在开发环境上的不同,包括开发语言、工具、平台特性等方面。通过对这些差异性的分析,帮助开发者更好地理解两大平台,以便在项目开发中做出更合适的技术选择。
|
4天前
|
Dart 前端开发 Android开发
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
1月前
|
搜索推荐 前端开发 API
探索安卓开发中的自定义视图:打造个性化用户界面
在安卓应用开发的广阔天地中,自定义视图是一块神奇的画布,让开发者能够突破标准控件的限制,绘制出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战技巧,逐步揭示如何在安卓平台上创建和运用自定义视图来提升用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开新的视野,让你的应用在众多同质化产品中脱颖而出。
65 19
|
1月前
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
70 14

热门文章

最新文章