最近研究了一下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; }