I have an app that uses a popupWindow for user chat. It is launched from a Fragment, and the supplied context is getActivity(). I will be typing in the popupWindow's multilineEditText and, after about 5 minutes or so, I will consistently get a crash with this error:
android.view.WindowManager$BadTokenException: Unable to add window -- token android.view.ViewRootImpl$W@d1cf1ec is not valid; is your activity running?
at android.view.ViewRootImpl.setView(ViewRootImpl.java:1147)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:471)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:95)
at android.widget.PopupWindow.invokePopup(PopupWindow.java:1621)
at android.widget.PopupWindow.showAtLocation(PopupWindow.java:1375)
at android.widget.PopupWindow.showAtLocation(PopupWindow.java:1341)
at android.widget.Editor$PinnedPopupWindow.updatePosition(Editor.java:3817)
at android.widget.Editor$PinnedPopupWindow.show(Editor.java:3773)
at android.widget.Editor$SuggestionsPopupWindow.show(Editor.java:4287)
at android.widget.Editor.replace(Editor.java:587)
at android.widget.-$$Lambda$DZXn7FbDDFyBvNjI-iG9_hfa7kw.run(Unknown Source:2)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:8167)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)
I know this isn't super helpful in explaining the error but, as far as I can tell, this is an issue with getActivity returning null and my popupWindow forcefully detaching from lack of context. Is there any way to avoid and/or fix this issue?
Below is some sample code for help with visualization of the popupWindow issue:
if(getActivity() != null) {
//Retrieve layout inflater
LayoutInflater layoutInflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (layoutInflater != null) {
//Inflate custom popup layout
View inflatedView = layoutInflater.inflate(R.layout.popup_chat_layout, null, false);
writeMessageEditText = inflatedView.findViewById(R.id.writeMessageEditText);
chatLayoutManager = new LinearLayoutManager(getActivity());
//Read from bottom-up
chatLayoutManager.setStackFromEnd(true);
chatMessagesRecycler.setLayoutManager(chatLayoutManager);
popupWindow = new PopupWindow(inflatedView, displayWidth, displayHeight, true);
popupWindow.setAnimationStyle(R.style.PopupAnimation);
popupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
popupWindow.setHeight(WindowManager.LayoutParams.MATCH_PARENT);
popupWindow.showAtLocation(v, Gravity.BOTTOM, 0, 0);
//Cap message lines - the purpose is not to cap characters, but ONLY to cap length
writeMessageEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (writeMessageEditText.getLayout().getLineCount() > 150) {
if (writeMessageEditText.getText() != null) {
writeMessageEditText.getText().delete(writeMessageEditText.getText().length() - 1, writeMessageEditText.getText().length());
}
Toast.makeText(getActivity(), "Message may not exceed 150 lines", Toast.LENGTH_SHORT).show();
}
}
});
//This was implemented during testing - possible to remove but fine for now
dismissChatButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
resetAll();
previousChat = null;
if(popupWindow != null) {
popupWindow.dismiss();
popupWindow = null;
}
}
});
}
}
Despite being dead-wrong regarding the cause of the core issue I was experiencing, I figure I may as well leave the question up for people who are just as bad at reading stack traces as me.
This may not be the perfect solution but, thanks to Mike M.'s comments, I was able to solve the immediate issue by disabling suggestion popups for the
EditTextin the xml file like so:Otherwise, the solution would be to replace the
PopupWindowwith aDialogorActivity.