My app consist of Fragments with fullscreen WebView. When user click on a link in the WebView then is opened new Fragment with new WebView with the same URL. Before open new Fragment I close soft keyboard just in case. I open new page very quick. All operations perform on the main thread.
By the Crashlytics the problem appers only on the Android 10 (all Pixel-series devices and other devices with 10). On devices before Android 10 all works fine. I can open much Fragments. But on Android 10 devices this case leads to FATAL EXCEPTION (after 2-3 quick attempts to open new page, randomly):
E/AndroidRuntime: FATAL EXCEPTION: pool-1-thread-1
Process: <myapp>, PID: 12487
java.lang.RuntimeException: Probable deadlock detected due to WebView API being called on incorrect thread while the UI thread is blocked.
at Yp.a(PG:13)
at com.android.webview.chromium.WebViewChromium.onCheckIsTextEditor(PG:4)
at android.webkit.WebView.onCheckIsTextEditor(WebView.java:3035)
at android.view.inputmethod.InputMethodManager.checkFocusNoStartInput(InputMethodManager.java:1901)
at android.view.inputmethod.InputMethodManager.checkFocus(InputMethodManager.java:1863)
at android.view.inputmethod.InputMethodManager.hideSoftInputFromWindow(InputMethodManager.java:1506)
at android.view.inputmethod.InputMethodManager.hideSoftInputFromWindow(InputMethodManager.java:1475)
at <myapp>.Utils.hideKeyboard(Utils.java:175)
at <myapp>.openNewPage(Pager.java:210)
...
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
Caused by: java.util.concurrent.TimeoutException
at java.util.concurrent.FutureTask.get(FutureTask.java:206)
at Yp.a(PG:11)
I tried to use all available versions of the Android System WebView (stable, beta, dev, canary) but nothing to help.
Anybody can help me?
Update:
If I comment code for hiding soft keyboard then all works fine.
This is not solution, only explain the issue.
First, you said "All operations perform on the main thread.", but it is wrong. The stack trees has indicated it is in a Worker thread.
And it is also can be confirmed from source code. WebView's blocking task.
Second, the code changed in Android Q, which checks view is text editor from this version.
Third, you post one task using View.post(). It is in UI thread, and the process is different in WebView (That is, it needn't wait and block)
In summary, InputMethodManager starts a task (WebView.onCheckIsTextEditor()) in non-UI thread, and WebView wants do it in UI thread, but it don't get result for timeout(4 seconds).
So it is because you have too much work in the UI thread
I think this is not the correct way to solve this problem, but it should work around this problem by extending WebView class and overriding onCheckIsTextEditor() method:
@Override
public boolean onCheckIsTextEditor() {
try {
return super.onCheckIsTextEditor();
} catch (Throwable th) {
// Probable deadlock detected due to WebView API being called on incorrect thread while the UI thread is blocked.
return true; // or return false in your scenario.
}
}
I have found a solution but not sure that it's correct. If anybody know the reason this crash or more elegant solution I'll be grateful.
Solution: wrap hideSoftInputFromWindow() in the View.post():
public static void hideKeyboard(@NotNull Context context, @NotNull View view, int flags) {
view.post(() ->
((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE))
.hideSoftInputFromWindow(view.getWindowToken(), flags));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With