2

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.

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115

1 Answers1

2

You can use ViewCompat.isAttachedToWindow() for the same purpose as view.isAttachedToWindow, but on API < 19

madless
  • 84
  • 6