美文网首页
android 9 启动登录界面编辑框有焦点无弹出全键盘

android 9 启动登录界面编辑框有焦点无弹出全键盘

作者: 小马要加油 | 来源:发表于2022-04-08 11:29 被阅读0次

    问题描述

    启动登录界面编辑框有焦点无弹出全键盘

    问题分析

    通过dumpsys input_methodke可以看到当前编辑框确实是有焦点的。

    查看代码

        override fun onResume() {
            super.onResume()
            if (mEditText?.requestFocus() == true) {
                val imm = context?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
                imm.showSoftInput(mEditText, InputMethodManager.SHOW_FORCED)
            }
        }
    

    在onResume时requestFocus如果拿到焦点,获取弹出全键盘。

     <activity
                android:name=".MainActivity"
                android:exported="true"
                android:label="@string/app_name"
                android:windowSoftInputMode="stateVisible|adjustResize"
                android:theme="@style/Theme.MalsDemo.NoActionBar">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
    

    在AndroidMainfest.xml中也有声明android:windowSoftInputMode ,可就是弹不出来。

    看log。

    把input相关的log都打开(这个打开需要源码支持。)

    2022-04-08 11:21:39.260 4369-4369/com.android.launcher3 V/InputMethodManager: focusOut: view=com.android.launcher3.allapps.AllAppsRecyclerView{41d7cd9 VFED..... .F...... 0,32-1920,1080 #7f0a0016 app:id/apps_list_view},focus=true,windowFocus=false,autofillUiShowing=false,window=android.view.ViewRootImpl$W@bc40603,temporaryDetach=false mServedView=com.android.launcher3.allapps.AllAppsRecyclerView{41d7cd9 VFED..... .F...... 0,32-1920,1080 #7f0a0016 app:id/apps_list_view},focus=true,windowFocus=false,autofillUiShowing=false,window=android.view.ViewRootImpl$W@bc40603,temporaryDetach=false
    2022-04-08 11:21:39.265 2071-2087/system_process D/InputMethodManagerService: --- calledFromForegroundUserOrSystemProcess ? calling uid = 10032 system uid = 1000 calling userId = 0, foreground user id = 0, calling pid = 12420com.android.server.InputMethodManagerService.showSoftInput(InputMethodManagerService.java:2585)
    2022-04-08 11:21:39.265 2071-2087/system_process W/InputMethodManagerService: Ignoring showSoftInput of uid 10032: com.android.internal.view.IInputMethodClient$Stub$Proxy@b46356
    2022-04-08 11:21:39.289 12420-12420/com.example.teamsdemo V/InputMethodManager: focusIn: androidx.appcompat.widget.AppCompatEditText{381cff VFED..CL. .F..H.ID 0,303-1920,363 #7f0801c8 app:id/textview_first},focus=true,windowFocus=true,autofillUiShowing=false,window=android.view.ViewRootImpl$W@f44b072,temporaryDetach=false
    2022-04-08 11:21:39.292 12420-12420/com.example.teamsdemo V/InputMethodManager: onWindowFocus: androidx.appcompat.widget.AppCompatEditText{381cff VFED..CL. .F..H.ID 0,303-1920,363 #7f0801c8 app:id/textview_first} softInputMode=STATE_ALWAYS_VISIBLE|ADJUST_RESIZE|IS_FORWARD_NAVIGATION first=true flags=#81810100
    2022-04-08 11:21:39.292 12420-12420/com.example.teamsdemo V/InputMethodManager: Restarting due to mRestartOnNextWindowFocus
    2022-04-08 11:21:39.293 12420-12420/com.example.teamsdemo V/InputMethodManager: focusIn: androidx.appcompat.widget.AppCompatEditText{381cff VFED..CL. .F..H.ID 0,303-1920,363 #7f0801c8 app:id/textview_first},focus=true,windowFocus=true,autofillUiShowing=false,window=android.view.ViewRootImpl$W@f44b072,temporaryDetach=false
    2022-04-08 11:21:39.293 12420-12420/com.example.teamsdemo V/InputMethodManager: checkFocus: view=androidx.appcompat.widget.AppCompatEditText{381cff VFED..CL. .F..H.ID 0,303-1920,363 #7f0801c8 app:id/textview_first} next=androidx.appcompat.widget.AppCompatEditText{381cff VFED..CL. .F..H.ID 0,303-1920,363 #7f0801c8 app:id/textview_first} forceNewFocus=true package=com.example.teamsdemo
    2022-04-08 11:21:39.293 12420-12420/com.example.teamsdemo V/InputMethodManager: Starting input: view=androidx.appcompat.widget.AppCompatEditText{381cff VFED..CL. .F..H.ID 0,303-1920,363 #7f0801c8 app:id/textview_first},focus=true,windowFocus=true,autofillUiShowing=false,window=android.view.ViewRootImpl$W@f44b072,temporaryDetach=false reason=WINDOW_FOCUS_GAIN
    2022-04-08 11:21:39.300 12420-12420/com.example.teamsdemo V/InputMethodManager: Starting input: tba=android.view.inputmethod.EditorInfo@e0d4fd2 ic=androidx.emoji2.viewsintegration.EmojiInputConnection@86928a3
    2022-04-08 11:21:39.300 12420-12420/com.example.teamsdemo V/InputMethodManager: START INPUT: view=androidx.appcompat.widget.AppCompatEditText{381cff VFED..CL. .F..H.ID 0,303-1920,363 #7f0801c8 app:id/textview_first},focus=true,windowFocus=true,autofillUiShowing=false,window=android.view.ViewRootImpl$W@f44b072,temporaryDetach=false ic=androidx.emoji2.viewsintegration.EmojiInputConnection@86928a3 tba=android.view.inputmethod.EditorInfo@e0d4fd2 controlFlags=#107
    2022-04-08 11:21:39.302 2071-3080/system_process D/InputMethodManagerService: --- calledFromForegroundUserOrSystemProcess ? calling uid = 10032 system uid = 1000 calling userId = 0, foreground user id = 0, calling pid = 12420com.android.server.InputMethodManagerService.startInputOrWindowGainedFocus(InputMethodManagerService.java:2754)
    2022-04-08 11:21:39.302 2071-3080/system_process V/InputMethodManagerService: windowGainedFocus: reason=WINDOW_FOCUS_GAIN client=android.os.BinderProxy@497f086 inputContext=com.android.internal.view.IInputContext$Stub$Proxy@d96afd7 missingMethods= attribute=android.view.inputmethod.EditorInfo@a0690c4 controlFlags=#107 softInputMode=STATE_ALWAYS_VISIBLE|ADJUST_RESIZE|IS_FORWARD_NAVIGATION windowFlags=#81810100 unverifiedTargetSdkVersion=32
    2022-04-08 11:21:39.302 2071-3080/system_process V/InputMethodManagerService: Window asks to always show input
    2022-04-08 11:21:39.302 2071-3080/system_process V/InputMethodManagerService: unbindCurrentInputLocked: client=android.os.BinderProxy@38c5d29
    2022-04-08 11:21:39.302 2071-3080/system_process V/InputMethodManagerService: Hide switching menu
    2022-04-08 11:21:39.302 2071-3080/system_process V/InputMethodManagerService: switching to client: client=android.os.BinderProxy@497f086 keyguard=false
    2022-04-08 11:21:39.303 4369-4369/com.android.launcher3 I/InputMethodManager: handleMessage: MSG_SET_ACTIVE false, was true
    2022-04-08 11:21:39.303 2071-3080/system_process V/InputMethodManagerService: Disabling: SessionState{uid 10009 pid 4369 method 897a721 session 4e829fb channel ClientState{411b9e3 uid 10009 pid 4369} (server)}
    2022-04-08 11:21:39.303 2071-3080/system_process V/InputMethodManagerService: Enabling: SessionState{uid 10032 pid 12420 method 897a721 session e838736 channel ClientState{28cee6a uid 10032 pid 12420} (server)}
    2022-04-08 11:21:39.303 4369-4369/com.android.launcher3 I/InputMethodManager: handleMessage: MSG_UNBIND 60 reason=SWITCH_CLIENT
    2022-04-08 11:21:39.303 4369-4369/com.android.launcher3 V/InputMethodManager: Clearing binding!
    2022-04-08 11:21:39.303 2071-3080/system_process D/InputMethodManagerService: showCurrentInputLocked: mCurToken=android.os.Binder@14f2b7b
    2022-04-08 11:21:39.303 2071-3080/system_process V/InputMethodManagerService: Calling com.android.internal.view.IInputMethod$Stub$Proxy@897a721.showSoftInput(0, null)
    2022-04-08 11:21:39.303 4714-4714/com.test.tvime V/InputMethodService: unbindInput(): binding=InputBinding{android.os.BinderProxy@86e0336 / uid 10009 / pid 4369} ic=InputConnectionWrapper{idHash=#7b6430e mMissingMethods=}
    2022-04-08 11:21:39.306 4714-4714/com.test.tvime V/InputMethodService: bindInput(): binding=InputBinding{android.os.BinderProxy@cd0033c / uid 10032 / pid 12420} ic=InputConnectionWrapper{idHash=#1f5d8c5 mMissingMethods=}
    2022-04-08 11:21:39.307 2071-2087/system_process D/InputMethodManagerService: --- calledFromForegroundUserOrSystemProcess ? calling uid = 10007 system uid = 1000 calling userId = 0, foreground user id = 0, calling pid = 4714com.android.server.InputMethodManagerService.reportFullscreenMode(InputMethodManagerService.java:4616)
    2022-04-08 11:21:39.314 4714-4714/com.test.tvime V/InputMethodService: startInput(): editor=android.view.inputmethod.EditorInfo@b17821a
    2022-04-08 11:21:39.314 12420-12420/com.example.teamsdemo V/InputMethodManager: Starting input: Bind result=InputBindResult{result=SUCCESS_WITH_IME_SESSION method=com.android.internal.view.IInputMethodSession$Stub$Proxy@3a27a0 id=com.test.tvime/com.test.ime.softkeyboard.IME sequence=61 userActionNotificationSequenceNumber=3}
    2022-04-08 11:21:39.316 4714-4714/com.test.tvime V/InputMethodService: CALL: onFinishInput
    2022-04-08 11:21:39.316 4714-4714/com.test.tvime V/InputMethodService: CALL: onStartInput
    2022-04-08 11:21:39.316 4714-4714/com.test.tvime V/InputMethodService: showSoftInput()
    2022-04-08 11:21:39.316 4714-4714/com.test.tvime V/InputMethodService: clearInsetOfPreviousIme()  mShouldClearInsetOfPreviousIme=false
    2022-04-08 11:21:39.339 12420-12420/com.example.teamsdemo I/InputMethodManager: handleMessage: MSG_SET_ACTIVE true, was false
    2022-04-08 11:21:39.757 4369-4369/com.android.launcher3 V/InputMethodManager: onViewDetachedFromWindow: view=android.view.View{436647f V.ED..... ......ID 385,70-473,158},focus=false,windowFocus=false,autofillUiShowing=false,window=android.view.ViewRootImpl$W@bc40603,temporaryDetach=false mServedView=com.android.launcher3.allapps.AllAppsRecyclerView{41d7cd9 VFED..... .F....ID 0,32-1920,1080 #7f0a0016 app:id/apps_list_view},focus=true,windowFocus=false,autofillUiShowing=false,window=android.view.ViewRootImpl$W@bc40603,temporaryDetach=false
    

    这边关键的log在这里,都走到InputMethodService的showSoftInput,还没显示全键盘。

    2022-04-08 11:21:39.316 4714-4714/com.test.tvime V/InputMethodService: showSoftInput()
    

    看源码

    //InputMethodService#showSoftInput ,传入参数(0,null)

    public void showSoftInput(int flags, ResultReceiver resultReceiver) {
                if (DEBUG) Log.v(TAG, "showSoftInput()");
                boolean wasVis = isInputViewShown();
                if (dispatchOnShowInputRequested(flags, false)) {
                    try {
                        showWindow(true);
                    } catch (BadTokenException e) {
                        // We have ignored BadTokenException here since Jelly Bean MR-2 (API Level 18).
                        // We could ignore BadTokenException in InputMethodService#showWindow() instead,
                        // but it may break assumptions for those who override #showWindow() that we can
                        // detect errors in #showWindow() by checking BadTokenException.
                        // TODO: Investigate its feasibility.  Update JavaDoc of #showWindow() of
                        // whether it's OK to override #showWindow() or not.
                    }
                }
                clearInsetOfPreviousIme();
                // If user uses hard keyboard, IME button should always be shown.
                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#dispatchOnShowInputRequested ,传入参数(0,false)

    private boolean dispatchOnShowInputRequested(int flags, boolean configChange) {
        final boolean result = onShowInputRequested(flags, configChange);
        if (result) {
            mShowInputFlags = flags;
        } else {
            mShowInputFlags = 0;
        }
        return result;
    }
    

    //InputMethodService#onShowInputRequested ,传入参数(0,false)

    public boolean onShowInputRequested(int flags, boolean configChange) {
        if (!onEvaluateInputViewShown()) {
            return false;
        }
        if ((flags&InputMethod.SHOW_EXPLICIT) == 0) {//true
            if (!configChange && onEvaluateFullscreenMode()) {true && false
                // Don't show if this is not explicitly requested by the user and
                // the input method is fullscreen.  That would be too disruptive.
                // However, we skip this change for a config change, since if
                // the IME is already shown we do want to go into fullscreen
                // mode at this point.
                return false;
            }
            if (!mSettingsObserver.shouldShowImeWithHardKeyboard() && //true && true
                    getResources().getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS) {
                // And if the device has a hard keyboard, even if it is
                // currently hidden, don't show the input method implicitly.
                // These kinds of devices don't need it that much.
                return false;
            }
        }
        return true;
    }
    

    //InputMethodService#onEvaluateInputViewShown

    public boolean onEvaluateInputViewShown() {
        if (mSettingsObserver == null) {
            Log.w(TAG, "onEvaluateInputViewShown: mSettingsObserver must not be null here.");
            return false;
        }
        if (mSettingsObserver.shouldShowImeWithHardKeyboard()) {
            return true;
        }
        Configuration config = getResources().getConfiguration();
        return config.keyboard == Configuration.KEYBOARD_NOKEYS
                || config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES;
    }
    

    SettingsObserver#shouldShowImeWithHardKeyboard()

    private boolean shouldShowImeWithHardKeyboard() {
        // Lazily initialize as needed.
        if (mShowImeWithHardKeyboard == ShowImeWithHardKeyboardType.UNKNOWN) {
            mShowImeWithHardKeyboard = Settings.Secure.getInt(mService.getContentResolver(),
                    Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0) != 0 ?
                    ShowImeWithHardKeyboardType.TRUE : ShowImeWithHardKeyboardType.FALSE;
        }
        switch (mShowImeWithHardKeyboard) {
            case ShowImeWithHardKeyboardType.TRUE:
                return true;
            case ShowImeWithHardKeyboardType.FALSE:
                return false;
            default:
                Log.e(TAG, "Unexpected mShowImeWithHardKeyboard=" + mShowImeWithHardKeyboard);
                return false;
        }
    }
    

    这边输入 settings get secure show_ime_with_hard_keyboard 获取到的值是0
    所以shouldShowImeWithHardKeyboard 返回false。导致没有执行到showWindow(),从而没有显示输入框.

    猜测

    settings put secure show_ime_with_hard_keyboard 1 把这个值设置为1,验证是否可行。
    从这边看,如果shouldShowImeWithHardKeyboard返回false,还会判断

    config.keyboard == Configuration.KEYBOARD_NOKEYS
                || config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES
    

    如果这边条件为true,也是可以走到下一个流程的。可以代码测试一下这个条件是否为真,我这边验证时可以的。

    config.keyboard == Configuration.KEYBOARD_NOKEYS // false
    config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES //true
    

    修改

    这边涉及到设备环境问题了。
    如果设备没有按键,那config.keyboard == Configuration.KEYBOARD_NOKEYS应该是true
    如果设备有按键的时候允许弹全键盘,那settings secure show_ime_with_hard_keyboard 这个值不应该设置为0.
    所以是我们设备的系统配置有问题。改上面的任一个条件都可。

    相关文章

      网友评论

          本文标题:android 9 启动登录界面编辑框有焦点无弹出全键盘

          本文链接:https://www.haomeiwen.com/subject/cafysrtx.html