Keeping track of View added to WindowManager (no findViewById() function?)
Asked Answered
A

5

20

In my service I add a view to WindowManager with addView(). When I'm ready to hide the view, I call removeView() using the View reference. This works great -- most of the time.

I have occasional Force Close reports that say that the View is not attached to the WindowManager. This makes sense. The problem is that I think the service is getting killed by Android, and when it is time to hide the view, it attempts to removeView on the wrong View.

I have tried checking for the View to be null, but apparently it isn't at this point, it simply isn't the one attached to the WindowManager. It seems that if the View reference is lost, there is no way to gain access to it again.

How can I get the equivalent of findViewById() on the WindowManager itself? Is the View automatically removed from WindowManager if my service is stopped (killed)? Is there a way I can store the reference to the View so that if the service is stopped I can still remove the View later (I'm also trying to avoid leaking the View)?

Aerostatics answered 29/6, 2011 at 1:58 Comment(3)
i know this is old but why are you interacting with the UI from a service?!?Bearable
@Bearable I wanted to override the incoming call screen, but there is no mechanism for doing this in Android (so far). Best solution is to show a view over the incoming call screen, and an Activity is unreliable for this. A service lets me keep track of the view and hide it when it is no longer needed.Aerostatics
Did you resoved?Plenitude
A
11

In my service I add a view to WindowManager with addView(). When I'm ready to hide the view, I call removeView() using the View reference. This works great--most of the time. I have occasional Force Close reports that say that the View is not attached to the WindowManager.

I am having the exact same problem. Hopefully an expert will chime in.

How can I get the equivalent of findViewById() on the WindowManager itself?

Keep a reference to the View that was added and simply use removeView(mView).

Currently in my Service, to add the view:

WindowManager.LayoutParams params = ...
mView = new View(this);
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(mView, params);

Then to remove the view, I avoid occasional FC by catching the exception:

WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
try {
    wm.removeView(mView);
} catch (Exception e) {}

Is the View automatically removed from WindowManager if my service is stopped (killed)?

In my experience, they are removed when the service is killed. You can test this by stopping your service without removing the views. No idea why that works though.

My concern is that my second reference to the WM is different when I go to remove the view. If that is the case, is mView still being displayed when I catch the exception? I would try keeping a reference to the WM when I add the view, but I've had issues where references to System Services seem to go bad over time.

Let me know if you ever solved this problem.

Altorilievo answered 22/7, 2011 at 22:45 Comment(4)
That's a very good question: does a new reference to WindowManager still give access to the original "mView" which was added to it? Other than that, your code looks essentially identical to what I'm using. Originally I wasn't catching the (seemingly random) exceptions around .removeView(), but now that I am I think the app is working much better. I still want to know if letting the View be automatically removed is acceptible practice, or if the View is actually leaking every time my service is killed! Thanks @kevin!Aerostatics
I am facing the same problem regarding to wm.removeView(mView);Finnish
The view isn't leaking in the error logs, I also use the catch statement to prevent this error. Right now I'm trying to track the count of the views displayed somewhat like Google does for tracking bitmaps and recycling them on older platforms. Check out the Google deverloper docs for using bitmaps efficiently to see some interesting tracking ideas (look under the older API section).Houri
I had a same problem? Is there any solution for this ?Plenitude
K
6

To check if view has been succesfully attached to Windows Manager, or is still attached, you can use view.isShown();.

Keyhole answered 22/4, 2015 at 1:5 Comment(1)
view.isShown returns false also if the view is attached to window but is not visible (it is invisible or gone) developer.android.com/reference/android/view/…Sennight
D
2

Check that the views parent != null before trying to remove it.

if(mView.getParent() != null){
   wm.removeView(mView);
}
Doublure answered 4/5, 2016 at 17:33 Comment(0)
F
2

You can also use:

ViewCompat.isAttachedToWindow(mView);

According the docs:

Returns true if the provided view is currently attached to a window.

Fated answered 15/12, 2016 at 11:5 Comment(0)
C
0

i have remove the layout by adding this code on an imageView

layoutView.findViewById(R.id.close).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

              windowManager.removeView(layoutView);
            }
        });
Ceiling answered 5/10, 2022 at 7:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.