下载安卓APP箭头
箭头给我发消息

客服QQ:3315713922

详细分析Android输入法框架的三大组件

作者:课课家教育     来源: http://www.kokojia.com点击数:1609发布时间: 2016-04-05 10:55:06

标签: Android框架Android输入法框架

  现在输入法在我们日常生活中是不可缺少的一部分了,因为现在科学技术的快速发展,很多电子产品都需要输入各种各样的字或者数字或者字母等输入,现在比较常见的是在手机端或者PC端上,都有使用各式各样的输入方式,比如搜狗、百度、五笔等。本文就详细介绍Android输入法框架的三大组件。

详细分析Android输入法框架的三大组件_Android框架_Android_输入法框架_课课家

  Android输入法框架(Input Method Framework,IMF)是Android中非常重要的模块,它分布于三个部分(确切的说,是三个进程),编辑框的客户、输入法服务和输入法管理者服务。编辑框的客户(Client)app,表示普通的使用输入法的app进程。当点击编辑框时,会切换出当前选中的输入法;当用户在输入法输入字符,提交候选词,则会更新到编辑框中。为了完成这些行为,它需要跟下面的两个输入法相关服务进行交互。对于普通app开发者而言,他们一般使用系统提供的EditText,该类和其父类TextView已经很好的封装了跟输入法服务之间的交互;如果是自定义的编辑框,则需要自己处理这种交互。输入法(input method,IME)服务(service),是具体的输入法进程,例如自带的拉丁输入法或者谷歌,搜狗等拼音输入法。它们一般提供一个输入窗口,可以根据用户的要求打开或者关闭;可以把用户输入的字符和提交的候选词更新给client等等。这是一个用户级别的Service。为了方便开发者编写新的输入法,IMF提供了抽象基类InputMethodService供输入法开发者扩展。输入法管理者(Input method manager,IMM)服务(Service),这是一个Android系统级的服务,用于管理多个输入法以及同其他系统服务(例如window manager service)进行交互。这部分代码是app开发者和IME开发者都不需要关心的。

  为了方便描述,后文分别称该三个组件为:client,IME和IMM。

  这三个部分需用共同合作才能完成输入法的工作。例如打开一个app,并且一个edit框获取了focus焦点。此时client会通知IMM打开输入法,然后IMM查看当前选中的IME,并调用该IME的start操作。这个简单的开始操作需要三个组件的配合。再比如用户提交了候选词,此时IME需要将候选词告诉client。这里须要IME和client的合作。

  因为这三个部分是三个进程,所以它们之间必须通过IPC进行通讯。在Android中,IPC机制是通过binder机制和aidl接口进行通信的。

  对于Client而言,它提供了两个接口IInputMethodClient.aidl和IInputContext.aidl。前者是供IMM调用的,后者是供IME调用的。IMM提供了接口IInputMethodManager.aidl供其他两个组件调用。IME提供了两个接口IInputMethod.aidl和IInputMethodSession.aidl,前者供IMM调用,后者供client直接调用。

  这些调用关系可以参考下图:

  这些接口定义都在java/com/android/internal/view目录下。那这些接口是如何实现的呢?

  先看client提供的接口。IInputContext是由同一目录下的IInputConnectionWrapper实现的。正如名字所说,它只是一个wrapper,它把接收到的IPC消息委托给你InputConnection的一个实现。例如对于EditText而言,实现是EditableInputConneciton。

  在调用方,IME也不是直接操作IInputContext接口。它会调用实现了InputConnection接口的InputConnectionWrapper(也在前面目录下)。该对象封装了从client传过来的IInputContext实例。

  对于IME对client的调用操作,它会经历下面流程(以调用commitText为例,它表示提交候选词):

  InputConnectionWrapper.commitText被IME进程中其他代码调用。委托给IInputContext stub对象。通过IPC跨进程传输IInputConnectionWrapper接受到该消息并调用其commitText处理。如果当前在主UI线程,则直接嗲用InputConnection的实现(例如EditableInputConnection)的commitText方法;否则通过handler进行线程间通信。

  在IME看来,接口是InputConnection;在client上,实现的也是InputConnection。IInputContext完全被隐藏起来了。所以Android官方文档说IME通过InputConnection接口来操作client。

  再看client提供的另外一个接口IInputMethodClient,IMM是直接调用的。IMM的代码就是InputMethodManagerService。在client端,InputMethodManager类中有一个对IInputMethodClient.stub的实现。

  对IMM提供的IInputMethodManager接口而言,它是由InputMethodManagerService来实现的。在client端,InputMethodManager的getInstance(是个singleton)会调用ServiceManager.getService(Context.INPUT_METHOD_SERVICE)获取该接口,然后创建InputMethodManager。所以对于client而言,它跟IMM的交互都是通过InputMethodManager来封装完成的,并不需要关心IInputMethodManager接口。对于IME,如果它想操作IMM,也同样通过InputMethodManager。

  下面是IME提供的接口。类似于使用InputConnection封装IInputContext,有两个接口InputMethod和InputMethodSession分别对应着了IInputMethod和IInputSession。

  对于InputMethod,IInputMethodWrapper实现了IInputMethod.stub。对于收的的IPC请求,都转发给InputMethod实例。一般而言,这个实例是InputMethodService中定义的InputMethodImpl。该实例是InputMethodService的内部类,所以可以操作InputMethodService。对于其客户IMM,InputMethodManagerService会直接调用IInputMethod的方法发起IPC请求。

  对于InputMethodSessoin,非常类似,IInputMethodSessionWrapper实现了IInputMethodSession.stub。同样在InputMethodService中有InputMethodSessionImpl实现了InputMethodSession接口,有一个该类型的对象在IInputMethodSessionWrapper中,负责具体处理过来的IPC消息。在client端,InputMethodManager有一个IInputMethodSession mCurMethod对象。开发者只需要调用InputMethodManager,而由InputMethodManager调用IInputMethodSession的IPC操作。

  总结一下,无论是client还是IME的开发者,都不需要直接操作aidl接口。在client端,对于IMM和IME的操作都是通过InputMethodManager发起的,用户甚至不用关心这些IPC操作是发给谁的;在IME端,开发者通过InputConnection给client发IPC消息,通过InputMethodManager给IMM发。而在IMM端,虽然是直接操作aidl接口的stub对象,但因为一般开发者不需要改写它,所以也无关紧要。通过这种方式,简化了开发者的跨进程操作。

  最后再总结下代码位置:

  所有的aidl接口都在java/com/android/internal/view目录下。它只是internal可见,所以普通开发者无法直接访问它。用户可以访问的接口或类,包括InputConnection,InputMethodManager,InputMethod,InputMethodSession都在java/android/view/inputmethod目录下。java/com/android/internal/view还包含IInputConnecitonWrapper,InputConnectionWrapper。java/android/view/inputmethod还包含BaseInputConnectionjava/android/inputmethodservice包含IME端相关代码,例如IInputMethodWrapper,IInputMethodSessionWrapper,InputMethodImpl,InputMethodSessionImpl,InputMethodService。IMM的InputMethodManagerService在services/java/com/android/server下。

  代码主要就是这四个目录。

     我们详细介绍了Android输入法框架的编辑框的客户、输入法服务和输入法管理者服务的三大部分,还详细介绍了三大组件操作接口的步骤,希望能帮助你理解Android输入法框架。

赞(1)
踩(0)
分享到:
华为认证网络工程师 HCIE直播课视频教程