Android的输入法框架

Android的输入法框架

转自:http://hi.baidu.com/leo10086/item/f81c0bfa6882aa19e3e3bd50

Android的输入法框架比价复杂。从进程的角度来讲,相关功能主要分布在下面三个位置:

  

 

客户端应用是一个包含有图形界面的应用,如地址本。图形界面上包含有能够接收输入的编辑框,如TextView。

输入法模块提供软键盘,将用户在软键盘上的按键输入根据某种算法(如Zi, T9, 国笔等)转换成单词,然后传递给客户端应用。目录development/samples/SoftKeyboard下提供了一个输入法模块实例。如果想要实现一个中文输入法,可参考这个实例。

平台部分实现一些管理功能,负责装载某个输入法模块,启动,终止该模块等。

相关代码主要位于下面几个位置。其中,位于3,5,6,7目录下的代码最值得关注。

1. frameworks/base/core/java/com/android/internal/view

这个目录下定义了几个重要的idl 接口。

IInputMethod.aidl 定义了IInputMethod idl 接口,用于客户端跨进程操作InputMethod接口。

IInputMethodSession.aidl 定义了IInputMethodSession接口,是IInputMethod的辅助接口。用于客户端跨进程操作InputMethodSession接口。

 

IInputMethodCallback.aidl定义了一个helper 接口,由客户端实现。IInputMethod.aidl和IInputMethodSession.aidl实例可以分别调用该接口中的不同方法

 

IInputMethodManager.aidl 定义了Input Method Manager的service接口。客户端通过InputMethodManager interface调用这个service。

InputMethodManagerService.java实现了IInputMethodManager.aidl接口

 

IInputMethodClient.aidl定义接口,标识一个Input Method Manager 的客户。这个service在客户端实现,提供给server端调用。

 

IInputContext.aidl定义了一个接口,由客户端提供InputMethod使用。InputMethod可以与客户端交互,调用客户端提供的callback。

IInputConnectionWrapper.java 实现了IInputContext接口。

IInputContextCallback.aidl定义了一个接口,定义了一组callback函数给IInputContext.aidl实例调用,从客户端返回信息给InputMethod。

InputConnectionWrapper.java实现了IInputContextCallback接口。

 

2. frameworks/base/services/java/com/android/server

InputMethodManagerService.java实现了IInputMethodManager.aidl接口

 

3. frameworks/base/core/java/android/view/inputmethod

这个目录下定义了几个重要的interface和类。

InputMethodManager.java实现了InputMethodManager 类。此类调用IInputMethodManager.aidl接口功能,而IInputMethodManager.aidl接口功能由InputMethodManagerService.java实现,并运行在不同于客户端进程的server进程中。

 

InputConnection.java定义了InputConnection interface。InputConnection 接口在输入法和客户端之间建立了一个连接,输入法可以使用该连接获取或发送信息给客户端。InputConnection实例由客户端创建之后传递给输入法使用。BaseInputConnection.java 实现了InputConnection接口的一个基类: BaseInputConnection。 EditableInputConnection.java实现了一个派生类

 

InputBinding.java 定义了类InputBinding,这个类实现了parcelable 接口。这个类的成员变量包含了客户端传向server的信息。

 

InputMethod.java定义了InputMethod interface。文件InputMethodService.java中类InputMethodImpl实现了这个接口。这个接口定义了一套操纵一 个输入法的方法。如,createSession,startInput等。要编写一个具体输入法的话,就需要派生这个接口。

 

InputMethodSession.java定义了InputMethodSession接口。文件InputMethodService.java 中类InputMethodSessionImpl实现了这个接口。InputMethodSession是InputMethod的辅助接口,用于具体 和某个输入法客户端交互。

 

CompletionInfo.java 类描述一个text completion.

EditorInfo.java类描述一个接收输入的view的属性,如内容属性(text, digit, etc)。

ExtractedText.java类描述从view中提取的传递给输入法的文本属性。

 

 

4. frameworks/base/core/java/com/android/internal/widget

EditableInputConnection.java实现了BaseInputConnection的一个派生类。

 

5. frameworks/base/core/java/android/inputmethodservice

这个目录下的代码提供了实现一个具体输入法的框架类。从这些类派生,就可以定制一个输入法。

SoftInputWindow.java中的SoftInputWindow类是一个Dialog子类。它代表一个输入法的顶级窗口(由窗口管理器管理),这个窗口由上到下,包含extractArea, candidatesArea, 和 inputArea。

 

Keyboard.java 中的Keyboard类装载并解析一个描述虚拟键盘(Soft Keyboard)的xml文件(如development/samples/SoftKeyboard/res/xml),并存储该键盘的属性,如该虚拟键盘包含多上行,每行有哪些键等。

KeyboardView.java 中的KeyboardView类是一个View子类。它根据Keyboard数据结构真正的在screen上画出一个虚拟键盘。这个虚拟键盘就是SoftInputWindow中的inputArea。

 

AbstractInputMethodService是Service的派生类,并实现了KeyEvent.Callback 接口。实现了InputMethod 和 InputMethodSession的基类。dispatchKeyEvent 函数将收到的key event传给相应的key 处理函数(在派生类中实现)。当这个service被客户端绑定时,其onBind()函数给客户端返回了一个IInputMethodWrapper实例,这个实例实现了IInputMethod idl接口。客户端可以使用该接口的相关功能。

 

IInputMethodWrapper.java 实现了IInputMethod idl 接口。这个类收到客户端的跨进程命令后,调用InputMethod完成相应功能。

IInputMethodSessionWrapper.java 实现了IInputMethodSession idl接口。这个类收到客户端的跨进程命令后,调用InputMethodSession完成相应功能。

 

 

6. frameworks/base/core/res/res/layout

这个目录下存放着一些系统资源。其中,

input_method.xml描述了一个输入法的窗口(即SoftInputWindow)布局,从上往下,依次排列extractArea, candidatesArea 和 inputArea。

input_method_extract_view.xml。

 

7. development/samples/SoftKeyboard

这个目录下代码实现了一个的输入法实例--软键盘英文/数字输入法。这里面实现的类大都是从frameworks/base/core/java/android/inputmethodservice 中的类派生而来。

AndroidManifest.xml:描述这个.apk提供的service以及关于这个输入法的一些信息。

res/xml/目录下存储着几个描述不同虚拟键盘的xml文件。

LatinKeyboard.java中的LatinKeyboard类是Keyboard的子类。

LatinKeyboardView.java中的LatinKeyboardView类是KeyboardView的子类。

 

8. frameworks/base/core/java/android/widget

在这里TextView.java是使用Input Method Framework (IMF)的客户端。TextView创建了一个InputMethodManager的实例并调用其restartInput 函数。

InputMethodManager::restartInput函数创建了一个InputConnection 实例并调用IInputMethodManager::startInput。

IInputMethodManager::startInput 函数使用mContext.bindService启动一个InputMethod service, 如 Sample Soft Keyboard。

 

9. frameworks/base/core/java/com/android/internal/widget

 

################################################## ####### 

 

  IMF是input method framework的简称, 它是Android 1.5新添加进去的一个重要功能,用来支持软键盘、各种的输入法。 

 

   到目前位置(2009-04-03),Android 1.5还没有正式发布,但IMF的功能已经很稳定,其上已经存在有3种输入法。分别是 

 

  LatinIME(软键盘)、 OpenWnn(CJK输入法)、PinyinIME(GOOGLE 拼音),还缺少中文的手写、五笔。 

 

   虽说按照已有的输入法模块, 也能写出自己想要的输入法。但是弄懂底层一些的东西,对于写新的输入法还是有帮助的。我 

 

  学习的目的就是这样。下面开始: 

 

  相关代码的位置: 

 

  frameworks/base/core/java/com/android/internal/vie w/ 

 

  IMF接口定义 

 

  frameworks/base/core/java/android/view/inputmothod / 

 

  IMF客户端 

 

  frameworks/base/core/java/android/inputmethodservi ce/ 

 

  IMF服务端 

 

  frameworks/base/services/java/com/android/server/I nputMethodManagerService.java 

 

  输入法管理服务 

 

  packages/inputmethods/ 

 

  现有的输入法 

 

  development/samples/SoftKeyboard/ 

 

  软键盘示例 

 

  frameworks/base/core/java/android/view/View.java 

 

  frameworks/base/core/java/android/widget/TextView. java 

 

  控件和输入法的交互 

 

  按照SDK文档的叙述,IMF包含3个主要部分: 

 

  1、input method manager (IMM) 

 

  相当于客户端的API,协调其它部分的互动,负责跟系统服务(IMMS) 通讯。 

 

  2、input method (IME) 

 

  界面和输入法引擎, 处理用户的输入。 

 

  3、client applications 

 

  传递一些信息, IMM用来决定焦点和IME状态, IME一次只能有一个Client连接。 

 

  InputMethodManager 

 

  实例化的时候, 会连接到IMMS服务,然后一些调用里会请求IMMS的服务。 

 

  InputMethodManagerService 

 

  处理来自InputMethodManager的请求,管理输入法服务。 

 

  初始化的时候,会做如下一些事情: 

 

  1、注册一些系统事件,处理事件(开关屏、关闭系统对话框、包改变)跟输入法的交互, 例如: 关屏时会把输入法菜单关闭; 

输入法包被删除时,将输入法从可用列表移除等。 

 

  2、加载输入法列表(buildInputMethodListLocked),读取启用的输入法,如果设置为空,加载全部输入法,并选择一个默认输入法。 

 

  3、加载状态栏图标、加载DB服务端。 

 

  View和输入法的交互 

 

  onFocusChanged() 

 

  失去焦点调用用imm.focusOut(), 得到焦点调用imm.focusIn() 

 

  onWindowFocusChanged 

 

  失去焦点调用用imm.focusOut(), 得到焦点调用imm.focusIn() 

 

  TextView和输入法的交互 

 

  setInputType() 

 

  改变输入法类型后, 会重启输入法imm.restartInput() 

 

  onEditorAction() 

 

  收到输入完成事件,隐藏输入法界面imm.hideSoftInputFromWindow() 

 

  onDraw() 

 

  输入框内容改变,更新输入法的内容imm.updateExtractedText 

 

  输入框文本被选择, 更新输入法的选择信息imm.updateSelection 

 

  输入框的光标位置改变, 更新输入法的光标位置imm.updateCursor 

 

  ps. imm.isWatchingCursor 

 

  onKeyUp() 

 

  收到KEYCODE_DPAD_CENTER按键事件, 显示输入法界面imm.showSoftInput,这个事件鼠标左键点击,都是输入框获取焦点。 

 

  收到KeyEvent.KEYCODE_ENTER按键事件,状态是输入完成,关闭输入法界面imm.hideSoftInputFromWindow() 

 

  onTouchEvent() 

 

  触屏事件, 输入框获取焦点, 显示输入法界面imm.showSoftInput 

 

  isInputMethodTarget() 

 

  调用imm.isActive(), 用来判断此控件是否启用输入法 

 

  onTextContextMenuItem() 

 

  如果用户选择了“切换输入法”(ID_SWITCH_INPUT_METHOD),显示输入法菜单imm.showInputMethodPicker 

 

  setKeyListener() 

 

  每次调用都重启输入法imm.restartInput() 

 

  setText() 

 

  输入框内容改变, 重启输入法imm.restartInput() 

 

  画出IMF略图, 比较容易理解个大概。 

 

  下一步: 

 

  1、Widget和IME之间的交互、数据流向 

 

  2、各个部分的具体分析 

 

  ################################################## ################# 

 

  InputConnection 

 

  代码: 

 

  接口定义 frameworks/base/core/java/android/view/inputmethod /InputConnection.java 

 

  基础实现 frameworks/base/core/java/android/view/inputmethod /BaseInputConnection.java 

 

  控件和输入法之间的数据交换通过InputConnection,InputConnection由输入控件的onCreateInputConnection创建。 

 

  通过这个InputConnection将输入法服务和控件帮定,建立连接, 输入法服务和控件的数据、事件交互都通过这个连接。 

 

  输入内容是通过事件来提交的, 在sendCurrentText函数里创建一个特殊设备KeyCharacterMap.BUILT_IN_KEYBOARD 

 

  的按键事件,然后发送ViewRoot.DISPATCH_KEY_FROM_IME消息给输入框的父窗体。 

 

  在ViewRoot(frameworks/base/core/java/android/view/ViewRoot.ja va )的handleMessage事件回调里会处理这个 

 

  事件,通过deliverKeyEventToViewHierarchy()再分发这个事件。 

 

  在deliverKeyEventToViewHierarchy()中会调用view.dispatchKeyEvent分发这个事件。 

 

  最终这个事件会被具体控件的按键回调函数处理,例如TextView是在doKeyDown里接收输入的字符。 

 

  InputMethodService 

 

  frameworks/base/core/java/android/inputmethodservi ce/InputMethodService.java 

 

  InputMethodService是一个输入法基类, 基类实现了大部分的基本接口。 

 

  一般输入法都需要从这个类里派生,然后根据需求来实现自己的接口, 就可以编写一个自己的输 

 

  入法。 

 

  例如要实现一个五笔输入法, 从这个类里继承, 然后重新实现一个五笔键盘和候选字的界面和产 

 

  生结果的接口。 

 

  代码文件里有很多的说明, SDK文档里也有。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值