日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android 输入法如何启动流程_Android输入法显示流程

發(fā)布時間:2023/12/15 Android 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 输入法如何启动流程_Android输入法显示流程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Android輸入法顯示方式大概分為兩種:用戶手動點擊輸入框和應用程序設置了輸入法自動顯示

本文基于Android9.x來分析

目錄

1 :viewClicked流程

1.1 viewClicked

1.2 checkFocus

1.3 startInputInner

1.4 startInputOrWindowGainedFocus

1.5 startInputLocked

1.6 startInputUncheckedLocked

1.7 attachNewInputLocked

1.7.1 處理返回的結果

2:showSoftInput流程

2.1 showSoftInput

2.2 IMMS#showSoftInput

2.3 showCurrentInputLocked

2.4 IMSInputMethodImplInputMethodImplInputMethodImplshowSoftInput

2.5 dispatchOnShowInputRequested

2.6 IMS$showWindow

2.7 showWindowInner

2:從用戶點擊輸入框開始

EditText本身是TextView的子類,觸摸事件的起點在TextView的onTouchEvent方法中

if (touchIsFinished && (isTextEditable() || textIsSelectable)) {

// Show the IME, except when selecting in read-only text.

final InputMethodManager imm = InputMethodManager.peekInstance();

viewClicked(imm);

if (isTextEditable() && mEditor.mShowSoftInputOnFocus && imm != null) {

imm.showSoftInput(this, 0);

}

// The above condition ensures that the mEditor is not null

mEditor.onTouchUpEvent(event);

handled = true;

}

2.1:viewClicked

protected void viewClicked(InputMethodManager imm) {

if (imm != null) {

imm.viewClicked(this);

}

}

2:2:InputMethodManager::viewClicked

public void viewClicked(View view) {

final boolean focusChanged = mServedView != mNextServedView;

checkFocus();

synchronized (mH) {

if ((mServedView != view && (mServedView == null

|| !mServedView.checkInputConnectionProxy(view)))

|| mCurrentTextBoxAttribute == null || mCurMethod == null) {

return;

}

try {

if (DEBUG) Log.v(TAG, "onViewClicked: " + focusChanged);

mCurMethod.viewClicked(focusChanged);

} catch (RemoteException e) {

Log.w(TAG, "IME died: " + mCurId, e);

}

}

}

mCurMethod代表的是一個binder代理對象,對應的是

IInputMethodSessionWrapper

2.3:IInputMethodSessionWrapper::viewClicked

@Override

public void viewClicked(boolean focusChanged) {

mCaller.executeOrSendMessage(

mCaller.obtainMessageI(DO_VIEW_CLICKED, focusChanged ? 1 : 0));

}

case DO_VIEW_CLICKED: {

mInputMethodSession.viewClicked(msg.arg1 == 1);

return;

}

InputMethodSession對應的是一個接口,其實現(xiàn)類為AbstractInputMethodSessionImpl,AbstractInputMethodSessionImpl本身是一個抽象類,InputMethodSessionImpl有繼承它,所以最終調(diào)用的是InputMethodSessionImpl的viewClicked

2.4::InputMethodSessionImpl::viewClicked

public void viewClicked(boolean focusChanged) {

if (!isEnabled()) {

return;

}

InputMethodService.this.onViewClicked(focusChanged);

}

2.5:InputMethodService::onViewClicked

public void onViewClicked(boolean focusChanged) {

// Intentionally empty

}

2.6:TextView::checkFocus

public void checkFocus() {

if (checkFocusNoStartInput(false)) {

startInputInner(InputMethodClient.START_INPUT_REASON_CHECK_FOCUS, null, 0, 0, 0);

}

}

2.7:startInputInner

這個方法主要是和輸入法服務建立連接以及綁定

try {

if (DEBUG) Log.v(TAG, “START INPUT: view=” + dumpViewInfo(view) + " ic="

  • ic + " tba=" + tba + " controlFlags=#"

  • Integer.toHexString(controlFlags));

final InputBindResult res = mService.startInputOrWindowGainedFocus(

startInputReason, mClient, windowGainingFocus, controlFlags, softInputMode,

windowFlags, tba, servedContext, missingMethodFlags,

view.getContext().getApplicationInfo().targetSdkVersion);

if (DEBUG) Log.v(TAG, “Starting input: Bind result=” + res);

if (res == null) {

Log.wtf(TAG, “startInputOrWindowGainedFocus must not return”

  • " null. startInputReason="

  • InputMethodClient.getStartInputReason(startInputReason)

  • " editorInfo=" + tba

  • " controlFlags=#" + Integer.toHexString(controlFlags));

return false;

}

if (res.id != null) {

setInputChannelLocked(res.channel);

mBindSequence = res.sequence;

mCurMethod = res.method;

mCurId = res.id;

mNextUserActionNotificationSequenceNumber =

res.userActionNotificationSequenceNumber;

} else if (res.channel != null && res.channel != mCurChannel) {

res.channel.dispose();

}

switch (res.result) {

case InputBindResult.ResultCode.ERROR_NOT_IME_TARGET_WINDOW:

mRestartOnNextWindowFocus = true;

break;

}

if (mCurMethod != null && mCompletions != null) {

try {

mCurMethod.displayCompletions(mCompletions);

} catch (RemoteException e) {

}

}

} catch (RemoteException e) {

Log.w(TAG, "IME died: " + mCurId, e);

}

mService表示的是Imms在客戶端的代理對象

2.8:IMMS::startInputOrWindowGainedFocus

final InputBindResult result;

if (windowToken != null) {

result = windowGainedFocus(startInputReason, client, windowToken, controlFlags,

softInputMode, windowFlags, attribute, inputContext, missingMethods,

unverifiedTargetSdkVersion);

} else {

result = startInput(startInputReason, client, inputContext, missingMethods, attribute,

controlFlags);

}

if (result == null) {

// This must never happen, but just in case.

Slog.wtf(TAG, “InputBindResult is @NonNull. startInputReason=”

  • InputMethodClient.getStartInputReason(startInputReason)

  • " windowFlags=#" + Integer.toHexString(windowFlags)

  • " editorInfo=" + attribute);

return InputBindResult.NULL;

}

windowToken這個地方不為null,代碼邏輯執(zhí)行的是windowToken

2.9:windowGainedFocus

ClientState cs = mClients.get(client.asBinder());

//在窗口添加的時候會創(chuàng)建一個會話session,在會話創(chuàng)建的時候添加的

// if (mService.mInputMethodManager != null) {

// mService.mInputMethodManager.addClient(client, inputContext,

// mUid, mPid);

//Session.java的構造方法中

} else {

client.setUsingInputMethod(false);

}

if (cs == null) {----->

throw new IllegalArgumentException("unknown client "

  • client.asBinder());

}

try {

if (!mIWindowManager.inputMethodClientHasFocus(cs.client)) {

return InputBindResult.NOT_IME_TARGET_WINDOW;

}

} catch (RemoteException e) {

}

if (!calledFromValidUser) {

hideCurrentInputLocked(0, null);

return InputBindResult.INVALID_USER;

}

if (mCurFocusedWindow == windowToken) {

if (attribute != null) {

return startInputUncheckedLocked(cs, inputContext, missingMethods,

attribute, controlFlags, startInputReason);

}

return new InputBindResult(

InputBindResult.ResultCode.SUCCESS_REPORT_WINDOW_FOCUS_ONLY,

null, null, null, -1, -1);

}

2.10:startInputUncheckedLocked

if (mCurId != null && mCurId.equals(mCurMethodId)) {

if (cs.curSession != null) {

return attachNewInputLocked(startInputReason,

(controlFlags&InputMethodManager.CONTROL_START_INITIAL) != 0);

}

if (mHaveConnection) {

if (mCurMethod != null) {

requestClientSessionLocked(cs);

return new InputBindResult( InputBindResult.ResultCode.SUCCESS_WAITING_IME_SESSION,

null, null, mCurId, mCurSeq,

mCurUserActionNotificationSequenceNumber);

} else if (SystemClock.uptimeMillis()

< (mLastBindTime+TIME_TO_RECONNECT)) {

return new InputBindResult( InputBindResult.ResultCode.SUCCESS_WAITING_IME_BINDING,

null, null, mCurId, mCurSeq,

mCurUserActionNotificationSequenceNumber);

} else {

EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME,

mCurMethodId, SystemClock.uptimeMillis()-mLastBindTime, 0);

}

}

}

return startInputInnerLocked();

2.11:attachNewInputLocked

final SessionState session = mCurClient.curSession;

executeOrSendMessage(session.method, mCaller.obtainMessageIIOOOO(

MSG_START_INPUT, mCurInputContextMissingMethods, initial ? 0 : 1 /* restarting */,

startInputToken, session, mCurInputContext, mCurAttribute));

if (mShowRequested) {----------->此時mShowRequested為false

showCurrentInputLocked(getAppShowFlags(), null);

}

return new InputBindResult(InputBindResult.ResultCode.SUCCESS_WITH_IME_SESSION,

session.session, (session.channel != null ? session.channel.dup() : null),

mCurId, mCurSeq, mCurUserActionNotificationSequenceNumber);

第一部分主要是應用程序app和輸入法服務IMMS建立連接

3:應用程序請求輸入法顯示

if (touchIsFinished && (isTextEditable() || textIsSelectable)) {

// Show the IME, except when selecting in read-only text.

final InputMethodManager imm = InputMethodManager.peekInstance();

viewClicked(imm);

if (isTextEditable() && mEditor.mShowSoftInputOnFocus && imm != null) {

imm.showSoftInput(this, 0);

}

// The above condition ensures that the mEditor is not null

mEditor.onTouchUpEvent(event);

handled = true;

}

3.1:showSoftInput

public boolean showSoftInput(View view, int flags, ResultReceiver resultReceiver) {

checkFocus();

synchronized (mH) {

if (mServedView != view && (mServedView == null

|| !mServedView.checkInputConnectionProxy(view))) {

return false;

}

try {

return mService.showSoftInput(mClient, flags, resultReceiver);---------->請求輸入法服務來顯示showSoftInput

} catch (RemoteException e) {

throw e.rethrowFromSystemServer();

}

}

}

3:2:IMMS::showSoftInput

try {

synchronized (mMethodMap) {

if (mCurClient == null || client == null

|| mCurClient.client.asBinder() != client.asBinder()) {

try {

if (!mIWindowManager.inputMethodClientHasFocus(client)) {

return false;

}

} catch (RemoteException e) {

return false;

}

}

return showCurrentInputLocked(flags, resultReceiver);

}

} finally {

Binder.restoreCallingIdentity(ident);

}

3:3:showCurrentInputLocked

boolean res = false;

if (mCurMethod != null) {

executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOO(

MSG_SHOW_SOFT_INPUT, getImeShowFlags(), mCurMethod,

resultReceiver));

mInputShown = true;

if (mHaveConnection && !mVisibleBound) {

bindCurrentInputMethodServiceLocked(

mCurIntent, mVisibleConnection, IME_VISIBLE_BIND_FLAGS);

mVisibleBound = true;

}

res = true;

} else if (mHaveConnection && SystemClock.uptimeMillis()

= (mLastBindTime+TIME_TO_RECONNECT)) {

EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME, mCurMethodId,

SystemClock.uptimeMillis()-mLastBindTime,1);

Slog.w(TAG, “Force disconnect/connect to the IME in showCurrentInputLocked()”);

mContext.unbindService(this);

bindCurrentInputMethodServiceLocked(mCurIntent, this, IME_CONNECTION_BIND_FLAGS);

} else {

}

3.4::MSG_SHOW_SOFT_INPUT消息處理

case MSG_SHOW_SOFT_INPUT:

args = (SomeArgs)msg.obj;

try {

if (DEBUG) Slog.v(TAG, "Calling " + args.arg1 + “.showSoftInput(”

  • msg.arg1 + ", " + args.arg2 + “)”);

((IInputMethod)args.arg1).showSoftInput(msg.arg1, (ResultReceiver)args.arg2);

} catch (RemoteException e) {

}

args.recycle();

return true;

((IInputMethod)args.arg1)代表的是arg2

public Message obtainMessageIOO(int what, int arg1, Object arg2, Object arg3) {

SomeArgs args = SomeArgs.obtain();

args.arg1 = arg2;

args.arg2 = arg3;

return mH.obtainMessage(what, arg1, 0, args);

}

arg2代表是IInputMethod mCurMethod;是一個binder代理對象,表示的是輸入法在IMMS的代理對象,通過這個對象我們可以訪問輸入法進程里面的方法

3.5:IInputMethodWrapper::showSoftInput

public void showSoftInput(int flags, ResultReceiver resultReceiver) {

mCaller.executeOrSendMessage(mCaller.obtainMessageIO(DO_SHOW_SOFT_INPUT,

flags, resultReceiver));

}

//最終調(diào)用的是inputMethod的showSoftInput,inputMethod是InputMethod,InputMethod是一個接口,需要找到其實現(xiàn)類

case DO_SHOW_SOFT_INPUT:

inputMethod.showSoftInput(msg.arg1, (ResultReceiver)msg.obj);

return;

3.6:InputMethodServic.InputMethodImpl.java

public void showSoftInput(int flags, ResultReceiver resultReceiver) {

boolean wasVis = isInputViewShown();

if (dispatchOnShowInputRequested(flags, false)) {

try {

showWindow(true);------>顯示輸入法窗口

} catch (BadTokenException e) {

}

}

clearInsetOfPreviousIme();

mImm.setImeWindowStatus(mToken, mStartInputToken,

mapToImeWindowStatus(isInputViewShown()), mBackDisposition);

if (resultReceiver != null) {

resultReceiver.send(wasVis != isInputViewShown()

? InputMethodManager.RESULT_SHOWN

(wasVis ? InputMethodManager.RESULT_UNCHANGED_SHOWN

InputMethodManager.RESULT_UNCHANGED_HIDDEN), null);

}

}

InputMethodService是輸入法服務,工作在輸入法應用的進程中

3.7:showWindow

try {

mWindowWasVisible = mWindowVisible;

mInShowWindow = true;

showWindowInner(showInput);

} catch (BadTokenException e) {

mWindowVisible = false;

mWindowAdded = false;

throw e;

} finally {

// TODO: Is it OK to set true when we get BadTokenException?

mWindowWasVisible = true;

mInShowWindow = false;

}

3.8:showWindowInner

void showWindowInner(boolean showInput) {

boolean doShowInput = false;

final int previousImeWindowStatus =

(mWindowVisible ? IME_ACTIVE : 0) | (isInputViewShown() ? IME_VISIBLE : 0);

mWindowVisible = true;

if (!mShowInputRequested && mInputStarted && showInput) {

doShowInput = true;

mShowInputRequested = true;

}

initialize();

updateFullscreenMode();

updateInputViewShown();

if (!mWindowAdded || !mWindowCreated) {

mWindowAdded = true;

mWindowCreated = true;

initialize();

View v = onCreateCandidatesView();

if (v != null) {

setCandidatesView(v);

}

}

if (mShowInputRequested) {

if (!mInputViewStarted) {

if (DEBUG) Log.v(TAG, “CALL: onStartInputView”);

mInputViewStarted = true;

onStartInputView(mInputEditorInfo, false);

}

} else if (!mCandidatesViewStarted) {

if (DEBUG) Log.v(TAG, “CALL: onStartCandidatesView”);

mCandidatesViewStarted = true;

onStartCandidatesView(mInputEditorInfo, false);

}

if (doShowInput) {

startExtractingText(false);

}

final int nextImeWindowStatus = mapToImeWindowStatus(isInputViewShown());

if (previousImeWindowStatus != nextImeWindowStatus) {

mImm.setImeWindowStatus(mToken, mStartInputToken, nextImeWindowStatus,

mBackDisposition);

}

if ((previousImeWindowStatus & IME_ACTIVE) == 0) {

if (DEBUG) Log.v(TAG, “showWindow: showing!”);

onWindowShown();

mWindow.show();---->輸入法窗口是一個對話框

mShouldClearInsetOfPreviousIme = false;

}

}

總結

以上是生活随笔為你收集整理的android 输入法如何启动流程_Android输入法显示流程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲一区二区三区日韩 | 久久久久噜噜噜亚洲熟女综合 | 日韩一级片一区二区 | 三级网站免费 | 国产高清久久 | 爱爱视频欧美 | 国产伦精品一区二区三区在线 | 亚洲精品av中文字幕在线在线 | 黑人玩弄人妻一区二区三区免费看 | 泽村玲子在线 | 国产美女91呻吟求 | 美女视频在线免费观看 | 成人91av| 99色视频| 午夜伦理在线观看 | 亚洲成人aa| 激情综合文学 | 亚洲精品视频网 | 午夜啪啪福利视频 | 九色福利视频 | 日韩福利 | 精品区| 色综合999 | 日韩久久久久久久 | 国产麻豆一区二区 | 国产日韩欧美精品在线 | 免费av成人 | 水牛影视av一区二区免费 | 久久天堂电影 | 欧美在线免费观看视频 | 欧美日韩v | 国产精品乱码久久久久久久久 | 精品一区二区三区精华液 | 中国丰满老妇xxxxx交性 | 亚洲少妇毛片 | 免费在线观看成人 | 99久久久国产精品 | 无码人妻aⅴ一区二区三区玉蒲团 | 夜夜骑天天干 | 狠狠干91| 成人影片网址 | 日韩不卡一二三 | 中文字幕欧美人妻精品一区蜜臀 | 欧美日韩在线直播 | 成年人视频在线免费观看 | 四虎在线观看 | 麻豆污视频 | 久久澡| 女人免费视频 | 亚洲天堂中文字幕在线观看 | 久久a视频| 91av免费观看| 日本午夜小视频 | 欧美理论视频 | 四虎三级 | 99久久久无码国产精品性青椒 | 成人三级在线视频 | 欧美精品亚洲精品 | www.av在线.com| 亚洲黄网在线 | 国产最新精品视频 | 超碰个人在线 | ,午夜性刺激免费看视频 | www.毛片com | 亚欧成人| 国产又粗又大又爽 | 国产精品久久久久久久久久久新郎 | 欧美亚洲另类图片 | 久久av色| 久久亚洲精少妇毛片午夜无码 | 欧美色妞网 | 伊人狼人影院 | 免费吸乳羞羞网站视频 | 欧美精品一区二区三区在线播放 | 日韩一区二区三区四区 | 亚洲av成人片色在线观看高潮 | av日韩一区二区三区 | 久久精品国产电影 | 国产高潮久久 | 精品女同一区二区 | 在线观看日本一区二区 | 中文有码在线观看 | 欧美日韩国产网站 | 男女拍拍拍网站 | 欧美性jizz18性欧美 | 国产第一精品视频 | 香港台湾日本三级大全 | 久久久久久黄色 | 国产黄色免费观看 | 亚洲黄色大片 | 一本大道久久精品 | 午夜影院免费在线观看 | 国产精品国语对白 | 狠狠搞av| 中文字幕精品国产 | 国产精品熟女视频 | 久久久久久久9999 | 亚洲第一伊人 | 日韩三级观看 |