Analysis on the process of pulling up the soft keyboard in Android WebView

Posted by hubardz on Thu, 10 Feb 2022 15:07:21 +0100

preface

This article is flutter_ hybird_ Practice and technology sharing of WebView cross process rendering One of the research notes in the development process. If there are errors, please point them out.

Source code analysis

First, let's take a general look at the inheritance structure of webview:

public class WebView extends MockView {
    ...
}

public class MockView extends FrameLayout {
    ...
}

It can be seen that the model and basic code of conduct of webview comply with view, so we can speculate that the way of operating the soft keyboard may be the same as that of the local app. Therefore, let's first understand how the app pulls up the soft keyboard.

about MockView My personal understanding and application in development will be shared in other articles.

App pull up soft keyboard process

Pulling up the soft keyboard is generally as follows:

private void test() {
    //Ask for focus
    editText.requestFocus();
    //Get the imm and call the corresponding method
    InputMethodManager manager = ((InputMethodManager)getContext()
                            .getSystemService(Context.INPUT_METHOD_SERVICE));
    if (manager != null) 
        manager.showSoftInput(v, 0);
}

It can be roughly inferred from the above code that this is a cross process behavior, and the internal process is roughly as follows:

  1. Through getcontext() Getsystemservice (context. Input_method_service)) get IMM
  2. IMM itself is not the agent of the input process. Its internal IInputMethodManager is the real binder agent
//When calling manager showSoftInput(v, 0); Time

public boolean showSoftInput(View view, int flags, ResultReceiver resultReceiver) {
    // ... Omit some codes
    synchronized (mH) {
        if (mServedView != view && (mServedView == null
                || !mServedView.checkInputConnectionProxy(view))) {
            return false;
        }

        try {
            //Instance of IInputMethodManager
            return mService.showSoftInput(mClient, flags, resultReceiver);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}

3. Then, the input process will pull up the soft keyboard and transfer the corresponding keyEvent back to the app process. Finally, through the dispatchKeyEvent(KeyEvent event) method, it will be distributed to the decor view of the top window and consumed by the internal view.

So far, we have a general understanding of the pulling up of the soft keyboard (app side). Based on this, let's analyze the pulling up process of webview.

webview pull up the soft keyboard process

Simply put, the essence of webview is chromium, and chromium The source code of is very huge. Directly picking the source code can be said to be looking for a needle in a haystack.

 Its workflow will be introduced in other articles

From the above section, we know that the behavior of webview is roughly the same as that of view, so we can try to push back. First, we copy the getSystemService method:

@Override
public Object getSystemService(@NonNull String name) {
    if(name.equals(Context.INPUT_METHOD_SERVICE)) {
        //Inside the method, we output the stack information of the current thread
        inputToggleDelegate.inputServiceCall();
    }
    return super.getSystemService(name);
}

Then, we open a website with an input box and click the input box to get the following log:

Through the log, you can get the control of the soft keyboard ImeAdapterImpl.java - Chromium Code Search updateState(...) Method.
It will be called internally showSoftKeyboard() method:

private void showSoftKeyboard() { 
    if (!isValid()) return; 
    if (DEBUG_LOGS) Log.i(TAG, "showSoftKeyboard"); 
    View containerView = getContainerView(); 
    mInputMethodManagerWrapper.showSoftInput(containerView, 0, getNewShowKeyboardReceiver()); 
    if (containerView.getResources().getConfiguration().keyboard 
            != Configuration.KEYBOARD_NOKEYS) { 
        mWebContents.scrollFocusedEditableNodeIntoView(); 
    } 
}

Next, take a look at minputmethodmanagerwrapper showSoftInput():

@Override 
public void showSoftInput(View view, int flags, ResultReceiver resultReceiver) { 

    //... Omit some codes
    showSoftInputInternal(view, flags, resultReceiver); 
}

private void showSoftInputInternal(View view, int flags, ResultReceiver resultReceiver) { 
    StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); // crbug.com/616283 
    try { 
        //Obtain activity through the weak reference of WindowAndroid, and finally obtain imm
        InputMethodManager manager = getInputMethodManager(); 
        if (manager != null) { 
            boolean result = manager.showSoftInput(view, flags, resultReceiver); 
            if (DEBUG_LOGS) Log.i(TAG, "showSoftInputInternal: " + view + ", " + result); 
        } 
    } finally { 
        StrictMode.setThreadPolicy(oldPolicy); 
    } 
}

Here, it will merge with the process in the previous section, and the distribution and consumption later are similar.

The process analysis of WebView pulling up the soft keyboard is over. Thank you for reading.

Topics: Front-end Android Design Pattern Flutter webview