Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running? #92

Closed
epool opened this issue Aug 14, 2020 · 7 comments
Assignees
Labels
discussion No specific way to implement, more discussion required. Released Released already on the latest version.

Comments

@epool
Copy link

epool commented Aug 14, 2020

Please complete the following information:

  • Library Version [v1.1.9]
  • Affected Device(s) [General]

Describe the Bug:

We are receiving this crash in our crashlytics console

Fatal Exception: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
       at android.view.ViewRootImpl.setView(ViewRootImpl.java:710)
       at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:342)
       at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:94)
       at android.widget.PopupWindow.invokePopup(PopupWindow.java:1380)
       at android.widget.PopupWindow.showAsDropDown(PopupWindow.java:1236)
       at android.widget.PopupWindow.showAsDropDown(PopupWindow.java:1193)
       at com.skydoves.balloon.Balloon$showAlignTop$$inlined$show$1.run(Balloon.java:1272)
       at android.os.Handler.handleCallback(Handler.java:751)
       at android.os.Handler.dispatchMessage(Handler.java:95)
       at android.os.Looper.loop(Looper.java:154)
       at android.app.ActivityThread.main(ActivityThread.java:6077)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)

This is a dummy implementation of our view for a reference implementation:

class MyCustomView(context: Context) : FrameLayout(context), LifecycleOwner {

    private val myLifeCycle: LifecycleRegistry = LifecycleRegistry(this)

    private val binding: MyCustomViewBinding by lazy {
        MyCustomViewBinding.inflate(
            LayoutInflater.from(context),
            this,
            true
        )
    }

    private val myBalloon by lazy {
        createBalloon(context) {
            setCornerRadius(4f)
            setPadding(14)
            setBackgroundColor(ContextCompat.getColor(context, R.color.text_black))
            setWidthRatio(1f)
            setTextResource(R.string.if_you_want_to_take_more_orders_turn_on_the_auto_acceptance)
            setTextColorResource(R.color.white)
            setTextSize(14f)
            setIconDrawable(context.getDrawableCompat(R.drawable.icon_close))
            setIconSize(16)
            dismissWhenClicked = true
            lifecycleOwner = this@MyCustomView
        }
    }

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        myLifeCycle.handleLifecycleEvent(Lifecycle.Event.ON_START)
    }

    override fun onDetachedFromWindow() {
        myLifeCycle.handleLifecycleEvent(Lifecycle.Event.ON_STOP)
        super.onDetachedFromWindow()
    }

    fun observe(viewModel: ViewModel) {
        viewModel.someLiveData.observe(this@MyCustomView) {
            myBalloon.showAlignTop(binding.someView)
        }
    }

}

Expected Behavior:

Don't receive these crashes.

@skydoves
Copy link
Owner

skydoves commented Aug 15, 2020

Hi, @epool !
Could you test using this way?

override fun onDetachedFromWindow() {
      myLifeCycle.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
      super.onDetachedFromWindow()
}

I think your Activity is destroyed but still seems to show and reference the destroyed Activity's context.
Or the custom view is used in a fragment?

@epool
Copy link
Author

epool commented Aug 17, 2020

@skydoves yes, it's being used in an Activity. The reason why I'm not using myLifeCycle.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY) is because the custom view is being added and removed from its parent programmatically and when it's added again after being removed I want to still listening the events, otherwise after the Lifecycle.Event.ON_DESTROY the custom view stops receiving the view model events. I'll try to use the activity as lifecycleOwner = . The weird thing is that the custom view is declared inside of the activity and has the same life cycle scope in theory.

@skydoves
Copy link
Owner

skydoves commented Oct 7, 2020

Hi, @epool!
Could you let me know about this issue going on?

@znakeeye
Copy link

This could happen if you show a tooltip in some event handler where the event is handled just after e.g. user has pressed the back button.

I tried safe-guarding by checking fragment.isAdded() and possibly also (don't remember) fragment.isRemoving() but it still crashed. My fix was to skip the tooltip entirely.

For sure, we need some extra checks when showing the balloon. Will try to isolate this in a sample project at some point. Did the OP solve this?

@sembozdemir
Copy link

This issue is also happening for my app. Stacktrace is the same. I use it in an activity. I also use LiveData.

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // other codes

        observeDownloadStoriesVisibility()

        // other codes

    }

    private fun observeDownloadStoriesVisibility() {
        getViewModel().showDownloadStoriesEvent.observe(this, Observer { visible ->

            zoomFrameLayoutStoriesContainer.isVisible = visible

            if (visible) {
                createBalloon(this) {
                    setArrowPosition(0.5f)
                    setArrowSize(12)
                    setArrowOrientation(ArrowOrientation.TOP)
                    setCornerRadius(6f)
                    setAlpha(0.9f)
                    setText(getString(R.string.download_stories).toUpperCase(Locale.getDefault()))
                    setTextSize(14f)
                    setTextTypeface(Typeface.BOLD)
                    setPadding(8)
                    setTextColorResource(R.color.white)
                    setBackgroundColorResource(R.color.color2)
                    setBalloonAnimation(BalloonAnimation.FADE)
                    setFocusable(false)
                    setLifecycleOwner(this@ZoomActivity)
                    setOnBalloonClickListener { zoomFrameLayoutStoriesContainer.performClick() }
                }.showAlignBottom(zoomFrameLayoutStoriesContainer, 0, 6)
            }

        })
    }

@skydoves skydoves self-assigned this Oct 19, 2020
@skydoves skydoves added discussion No specific way to implement, more discussion required. Release Next This feature will be released on next version labels Oct 19, 2020
skydoves added a commit that referenced this issue Oct 19, 2020
@skydoves
Copy link
Owner

skydoves commented Nov 7, 2020

@znakeeye @sembozdemir
I released a new version 1.2.5.
This update includes preventing to show popups in activities when the window is already detached from the activities.
Please let me know if the same crash continues. Thanks!

@znakeeye
Copy link

@skydoves @sembozdemir
So far, I have not been able to reproduce this error in my setup. Very encouraging! Would be great if someone could confirm the fix in a published app.

@skydoves skydoves added Released Released already on the latest version. and removed Release Next This feature will be released on next version labels Nov 11, 2020
jimmithy added a commit to jimmithy/Balloon that referenced this issue Apr 4, 2024
An alternative approach to skydoves#92 to avoid any reference to the activity

isAttachedToWindow will confirm that the anchor view has a valid window token.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion No specific way to implement, more discussion required. Released Released already on the latest version.
Projects
None yet
Development

No branches or pull requests

4 participants