Android 7.0下Monkey测试触发焦点相关IllegalStateException问题求助
I ran into this java.lang.IllegalStateException: focus search returned a view that wasn't able to take focus! crash in com.android.launcher3 during Monkey testing a while back—let’s break down the root cause and actionable fixes.
What’s Causing This?
Looking at your crash log and code, here’s the breakdown:
- The crash originates in
TextView.onKeyUp()when the system tries to find the next focusable view after a key event, but the returned view can’t actually take focus. - In your
AllAppsContainerView.dispatchKeyEvent()logic, when a non-whitespace key is pressed, you immediately callmSearchBarController.focusSearchField()to focus the search box. - Monkey’s rapid, random key presses trigger this logic while the UI is still in a transitional state (e.g., the all-apps view is animating in, or the search box hasn’t fully initialized its focus state). When the system tries to resolve focus during the key event processing, it finds a view that’s not yet ready to accept focus, triggering the hard exception in TextView’s key handling.
Your ExtendedEditText has the right focus attributes, but the timing of the focus request during the key event lifecycle creates a race condition with the UI’s state.
Fixes to Resolve the Crash
1. Delay the Focus Request to Avoid Race Conditions
Modify the dispatchKeyEvent() logic to post the focus request to the main thread’s message queue, so it runs after the current key event is fully processed. This gives the UI time to stabilize before changing focus:
@Override public boolean dispatchKeyEvent(KeyEvent event) { if (!mSearchBarController.isSearchFieldFocused() && event.getAction() == KeyEvent.ACTION_DOWN) { final int unicodeChar = event.getUnicodeChar(); final boolean isKeyNotWhitespace = unicodeChar > 0 && !Character.isWhitespace(unicodeChar) && !Character.isSpaceChar(unicodeChar); if (isKeyNotWhitespace) { boolean gotKey = TextKeyListener.getInstance().onKeyDown(this, mSearchQueryBuilder, event.getKeyCode(), event); if (gotKey && mSearchQueryBuilder.length() > 0) { // Post to run after current key event completes post(() -> mSearchBarController.focusSearchField()); } } } return super.dispatchKeyEvent(event); }
2. Add Defensive Handling in the Custom EditText
Since the crash is thrown from TextView.onKeyUp(), you can wrap this logic in a try-catch in your ExtendedEditText to prevent the app from crashing, even if the focus search fails:
public class ExtendedEditText extends AppCompatEditText { // ... existing code ... @Override public boolean onKeyUp(int keyCode, KeyEvent event) { try { return super.onKeyUp(keyCode, event); } catch (IllegalStateException e) { Log.w("ExtendedEditText", "Ignoring focus search failure during key up", e); return false; } } // Optional: Improve focus search behavior @Override public View focusSearch(int direction) { View nextView = super.focusSearch(direction); // Ensure the next view is actually focusable before returning it if (nextView != null && !nextView.isFocusable()) { return this; } return nextView; } }
3. Adjust Monkey Test Parameters (Temporary Mitigation)
If you need a quick fix for testing, increase the --throttle value to give the UI more time to handle state changes between Monkey actions:
adb shell monkey -p com.android.contacts --throttle 500 -v 10000000
This won’t fix the underlying code issue, but it reduces the chance of hitting the race condition during testing.
Why This Works
Android’s focus management and key event processing run on the main thread. By delaying the focus request, you avoid modifying focus state in the middle of a key event’s lifecycle, which eliminates the race condition that causes the invalid focus search result. The defensive try-catch and improved focus search logic add safeguards for edge cases that might still slip through.
内容的提问来源于stack exchange,提问作者ShuRan.Ning

