Android输入法框架中按键消息的处理流程

最近研究了一下Android输入法,发现Android输入法框架中按键消息的处理流程和一般应用程序的处理流程有很大的不同,故在此做个总结。

一、一些名词缩写

IMF(Input MethodFramework):输入法框架

IM(Input Method):输入法

IMS(Input Method Service):输入法服务,一般指一个具体输入法对应的服务

IMMS(Input Method ManagerService):输入法管理器服务,系统进程的一部分,系统中只有一个该服务的实例

IMM(Input Method Manager):输入法管理器,每个客户进程中都包含一个

IME(Input Method Engine/InputMethod Editor):指一个具体的输入法,包括其内部的IMS和Binder对象

CA(Client Application):客户端进程,这里指使用输入法的进程。

二、输入法框架

1、  客户端进程(CA):在每个CA中都存在唯一一个IMM,UI控件(View,TextView,EditText等)可以通过它来访问IMMS,用来操作输入法,比如,打开,关闭,切换输入法等。可以通过Context.getSystemService()来获取一个InputMethodManager的实例。

IMM中有2个Binder对象,一个是可编辑UI控件对应的Binder对象(InputContext),输入法进程可以通过InputContext将虚拟按键事件(即通过触屏消息转换而来的按键事件)传递给UI控件;另一个是InputMethodClient,IMMS将通过它访问CA,例如IMMS通过它将IMS的InputMethodSession传递给CA,从而使得CA可以直接访问IMS。

2、输入法进程:和客户端进程类似,它也有2个Binder对象,一个是IMS对应的Binder对象,IMMS将通过它去控制输入法,例如:显示或者隐藏输入法窗口;另一个是专门供客户端使用的Binder对象,客户端主要通过它来向输入法进程传送按键事件。

具体可参见下图:


三、按键消息的处理流程

具体请见下图:


四、外界物理键盘的判断
当外接物理键盘连接android设备后,可以通过Configuration.KEYBOARD_QWERTY来判断。这里例子可以参见InputMethodService.java中关于软键盘是否显示的判断,代码如下:

    /**
     * Override this to control when the soft input area should be shown to
     * the user.  The default implementation only shows the input view when
     * there is no hard keyboard or the keyboard is hidden.  If you change what
     * this returns, you will need to call {@link #updateInputViewShown()}
     * yourself whenever the returned value may have changed to have it
     * re-evaluated and applied.
     */
    public boolean onEvaluateInputViewShown() {
        Configuration config = getResources().getConfiguration();
        return config.keyboard == Configuration.KEYBOARD_NOKEYS
                || config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES;
    }


Android 系统的键盘事件 是由InputManagerService 来监控的, 而InputManagerService 是由 SystemServer 来启动的 创建了一个类的对象 WindowInputEvent Receiver InputEventRe ceiver的构造 函数 WindowInputEventReceiver extends InputEventReceiver nativeInit InputEventReceiver.cpp nativeInit android_view_InputE ventReceiver.cpp NativeInputE ventReceiver 的构造函数 LooperCallback: :handleEvent NativeInputEve ntReceiver::ha ndleEvent Looper::p ollInner Looper::p ollOnce NativeInputEventRecei ver : public LooperCallback 有方法 NativeInputEventReceiver:: handleEvent 没有键盘事件发生, InputManager 的InputReader 正在睡眠等待键盘事件 的发生,而InputManager 的 InputDispatcher 正在等待InputReader 从睡眠醒过来并且唤醒它,而应用程 序也正在消息循环等待InputDispatcher 从睡眠醒过来并且唤醒它。 分析InputManager 分发键盘消息给应用程序的过程 InputReader .pollOnce EventHub.g etEvent InputReader::pr ocessEventsLock ed InputReader::pr ocessEventsForD eviceLocked InputDevic e::process 没有键盘事件发生, InputReaderThread 线程就会睡眠在EventHub.getEvent 函数 上,当键盘事件发生后,就会把这个事件封 装成一个RawEvent 对象,然后返回到 pollOnce函数,执行此函数 有键盘事件 InputReader.cpp InputMapper::process( 这里 是KeyboardInputMapper) InputReader::createDeviceLock ed根据类型创建的,负责处理轨迹 球事件的TrackballInputMapper 对 象以及负责处理触摸屏事件的 TouchInputMapper 对象等 KeyboardInputMap per::processKey 这个函数首先对对按 键作一些处理,例如 需要根据当时屏幕的 方向来调整键盘码 InputDispatcher::notify Key( 继承自 InputListenerInterface) KeyboardInputMappge r函数通知 InputDispatcher ,有 键盘事件发生了 1. 调用 validateKeyEvent 函数来验 证action参数是否正确 2. 参数action检查通过后,还通过 policyFlags 参数来检查一下同时是 否有ALT和SHIFT键被按下 3. 调用 enqueueInboundEventLocked 函数 把这个按键事件封装成一
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值