I have an Android application crash, when the orientation is changed (rotated), because focus change tries to render a dropdown list on an AppCompatAutoCompleteTextView, that has already lost its parent window (I suppose).
Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
This happens only when the focus is already in that view when the orientation changes... I'm a little surprised that the view receives a focus change event when rotating device (emulator).
The view in question is in XML as follows:
<androidx.appcompat.widget.AppCompatAutoCompleteTextView
android:id="@+id/dropdown_view"
android:inputType="textAutoComplete"
android:selectAllOnFocus="true"/>
The onFocusChangeListener of the view that crashes is declared in an androidx.fragment.app.Fragment(), in onViewCreated:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
...
dropdownView.setOnFocusChangeListener { view, hasFocus ->
if (hasFocus) {
editUnitView.showDropDown() //<<< Crash here on rotation, Caused by: android.view.WindowManager$BadTokenException:
// Unable to add window -- token null is not valid; is your activity running?
} else {
editUnitView.dismissDropDown()
}
}
...
}
If I set that onFocusChangeListener = null in onPause or onStop, it doesn't seem prevent the above listener to be called!
Anyway, I found one fix that seems to work:
dropdownView.setOnFocusChangeListener { view, hasFocus ->
if(view.isAttachedToWindow) { // Requires API 19
if (hasFocus) {
editUnitView.showDropDown()
} else {
editUnitView.dismissDropDown()
}
}
}
Sadly, I was targeting to API 15, and I'd like to keep that.
My question: Would you please have any ideas or suggestions, how to implement a safeguard not to request rendering of a dropdown menu (or anything else) to a window that already has gone away? Especially API level < 19.