android输入法架构解析
简介:
前阵子接手维护了一个密码键盘的项目,之前还没有接触过android输入法这块的知识点,所以在熟悉项目的同时将android系统输入法实现框架整理了一遍,记录在此.整个输入法架构可以简单划分为主要三块:
1.android输入法管理服务InputMethodManagerService(IMMS)
2.android输入法管理InputMethodManager(IMM)与当前输入控件(EditText)
3.输入法IME
简要示意图如下:
几个主要类关系图如下:
以下将按照如下流程分别进行介绍:
1.输入法管理服务InputMethodManagerService(IMMS)简介
2.输入法管理InputMethodManager(IMM)简介
3.输入法服务InputMethodService简介
4.从edittext点击到输入法界面显示过程
5.输入法字符传递到edittext过程
1.输入法管理服务InputMethodManagerService简介
IMMS主要管理输入法,通过接收IMM的请求拉起或者隐藏输入法,保持输入法与IMM的连接,系统服务的启动在systemserver中,输入法管理是在startOtherServices中:
if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
mSystemServiceManager.startService(InputMethodManagerService.Lifecycle.class);
......
}
进入到InputMethodManagerService中主要进行初始化操作,比如当前安装的输入法列表,设置默认输入法,运行时序图如下:
这里获取默认输入法列表和设置默认输入法的操作都在初始化方法中完成:
public InputMethodManagerService(Context context) {
mIPackageManager = AppGlobals.getPackageManager();
mContext = context;
mRes = context.getResources();
mHandler = new Handler(this);
// 这里后续会用来注册几个数据字段的监听
mSettingsObserver = new SettingsObserver(mHandler);
mIWindowManager = IWindowManager.Stub.asInterface(
ServiceManager.getService(Context.WINDOW_SERVICE));
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
mCaller = new HandlerCaller(context, null, new HandlerCaller.Callback() {
@Override
public void executeMessage(Message msg) {
handleMessage(msg);
}
}, true /*asyncHandler*/);
mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
mUserManager = mContext.getSystemService(UserManager.class);
mHardKeyboardListener = new HardKeyboardListener();
mHasFeature = context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_INPUT_METHODS);
//获取默认的系统设置
mSlotIme = mContext.getString(com.android.internal.R.string.status_bar_ime);
mHardKeyboardBehavior = mContext.getResources().getInteger(
com.android.internal.R.integer.config_externalHardKeyboardBehavior);
//初始化通知
Bundle extras = new Bundle();
extras.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, true);
mImeSwitcherNotification = new Notification.Builder(mContext)
.setSmallIcon(com.android.internal.R.drawable.ic_notification_ime_default)
.setWhen(0)
.setOngoing(true)
.addExtras(extras)
.setCategory(Notification.CATEGORY_SYSTEM)
.setColor(com.android.internal.R.color.system_notification_accent_color);
Intent intent = new Intent(Settings.ACTION_SHOW_INPUT_METHOD_PICKER);
mImeSwitchPendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
mShowOngoingImeSwitcherForPhones = false;
//注册用户添加移除,从备份中恢复系统设置广播
final IntentFilter broadcastFilter = new IntentFilter();
broadcastFilter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
broadcastFilter.addAction(Intent.ACTION_USER_ADDED);
broadcastFilter.addAction(Intent.ACTION_USER_REMOVED);
broadcastFilter.addAction(Intent.ACTION_SETTING_RESTORED);
mContext.registerReceiver(new ImmsBroadcastReceiver(), broadcastFilter);
mNotificationShown = false;
int userId = 0;
try {
userId = ActivityManagerNative.getDefault().getCurrentUser().id;
} catch (RemoteException e) {
Slog.w(TAG, "Couldn't get current user ID; guessing it's 0", e);
}
//注册app相关操作广播,包括安装卸载清除数据改变停止等
mMyPackageMonitor.register(mContext, null, UserHandle.ALL, true);
//初始化mSettings,后续用来存放和获取一些InputMethod设置相关内容
mSettings = new InputMethodSettings(