1 Android 输入法框架源码分析总结( 六 )


6.5传递输入法接口给程序端
// InputMethodManagerService.javavoid onSessionCreated(IInputMethod method, IInputMethodSession session,InputChannel channel) {synchronized (mMethodMap) {if (mCurMethod != null && method != null&& mCurMethod.asBinder() == method.asBinder()) {if (mCurClient != null) {clearClientSessionLocked(mCurClient);mCurClient.curSession = new SessionState(mCurClient,method, session, channel);InputBindResult res = attachNewInputLocked(true);if (res.method != null) {executeOrSendMessage(mCurClient.client, mCaller.obtainMessageOO(MSG_BIND_CLIENT, mCurClient.client, res));}return;}}}// Session abandoned.Close its associated input channel.channel.dispose();}
6.5绑定输入法和焦点view
// 输入法和view绑定InputBindResult attachNewInputLocked(boolean initial) {if (!mBoundToMethod) {executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(MSG_BIND_INPUT, mCurMethod, mCurClient.binding));mBoundToMethod = true;}final SessionState session = mCurClient.curSession;if (initial) {executeOrSendMessage(session.method, mCaller.obtainMessageIOOO(MSG_START_INPUT, mCurInputContextMissingMethods, session, mCurInputContext,mCurAttribute));} else {executeOrSendMessage(session.method, mCaller.obtainMessageIOOO(MSG_RESTART_INPUT, mCurInputContextMissingMethods, session, mCurInputContext,mCurAttribute));}if (mShowRequested) {if (DEBUG) Slog.v(TAG, "Attach new input asks to show input");showCurrentInputLocked(getAppShowFlags(), null);}return new InputBindResult(session.session,(session.channel != null ? session.channel.dup() : null),mCurId, mCurSeq, mCurUserActionNotificationSequenceNumber);}case MSG_BIND_INPUT:args = (SomeArgs)msg.obj;try {((IInputMethod)args.arg1).bindInput((InputBinding)args.arg2);} catch (RemoteException e) {}args.recycle();return true;case MSG_START_INPUT: {int missingMethods = msg.arg1;args = (SomeArgs) msg.obj;try {SessionState session = (SessionState) args.arg1;setEnabledSessionInMainThread(session);session.method.startInput((IInputContext) args.arg2, missingMethods,(EditorInfo) args.arg3);} catch (RemoteException e) {}args.recycle();return true;}case MSG_BIND_CLIENT: {args = (SomeArgs)msg.obj;IInputMethodClient client = (IInputMethodClient)args.arg1;InputBindResult res = (InputBindResult)args.arg2;try {// 调回到程序端,InputMethodManager.onBindMethod()client.onBindMethod(res);} catch (RemoteException e) {Slog.w(TAG, "Client died receiving input method " + args.arg2);} finally {// Dispose the channel if the input method is not local to this process// because the remote proxy will get its own copy when unparceled.if (res.channel != null && Binder.isProxy(client)) {res.channel.dispose();}}args.recycle();return true;}// IInputMethodWrapper.java @Overridepublic void startInput(IInputContext inputContext,@InputConnectionInspector.MissingMethodFlags final int missingMethods,EditorInfo attribute) {mCaller.executeOrSendMessage(mCaller.obtainMessageIOO(DO_START_INPUT,missingMethods, inputContext, attribute));}case DO_START_INPUT: {SomeArgs args = (SomeArgs)msg.obj;int missingMethods = msg.arg1;// IInputContext就是输入法和文本输入view的通信接口// 通过这个接口,输入法能够获取view的信息,也能够直接将文本传送给viewIInputContext inputContext = (IInputContext)args.arg1;InputConnection ic = inputContext != null? new InputConnectionWrapper(inputContext, missingMethods) : null;EditorInfo info = (EditorInfo)args.arg2;info.makeCompatible(mTargetSdkVersion);inputMethod.startInput(ic, info);args.recycle();return;}// InputMethodService.javapublic void startInput(InputConnection ic, EditorInfo attribute) {if (DEBUG) Log.v(TAG, "startInput(): editor=" + attribute);doStartInput(ic, attribute, false);}void doStartInput(InputConnection ic, EditorInfo attribute, boolean restarting) {if (!restarting) {doFinishInput();}mInputStarted = true;mStartedInputConnection = ic;mInputEditorInfo = attribute;initialize();if (DEBUG) Log.v(TAG, "CALL: onStartInput");onStartInput(attribute, restarting);if (mWindowVisible) {if (mShowInputRequested) {if (DEBUG) Log.v(TAG, "CALL: onStartInputView");mInputViewStarted = true;onStartInputView(mInputEditorInfo, restarting);startExtractingText(true);} else if (mCandidatesVisibility == View.VISIBLE) {if (DEBUG) Log.v(TAG, "CALL: onStartCandidatesView");mCandidatesViewStarted = true;onStartCandidatesView(mInputEditorInfo, restarting);}}}