What is this error, and why does it happen?
05-17 18:24:57.069: ERROR/WindowManager(18850): Activity com.mypkg.myP has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@44c46ff0 that was originally added here
05-17 18:24:57.069: ERROR/WindowManager(18850): android.view.WindowLeaked: Activity ccom.mypkg.myP has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@44c46ff0 that was originally added here
05-17 18:24:57.069: ERROR/WindowManager(18850): at android.view.ViewRoot.<init>(ViewRoot.java:231)
05-17 18:24:57.069: ERROR/WindowManager(18850): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)
05-17 18:24:57.069: ERROR/WindowManager(18850): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
05-17 18:24:57.069: ERROR/WindowManager(18850): at android.view.Window$LocalWindowManager.addView(Window.java:424)
05-17 18:24:57.069: ERROR/WindowManager(18850): at android.app.Dialog.show(Dialog.java:239)
05-17 18:24:57.069: ERROR/WindowManager(18850): at com.mypkg.myP$PreparePairingLinkageData.onPreExecute(viewP.java:183)
05-17 18:24:57.069: ERROR/WindowManager(18850): at android.os.AsyncTask.execute(AsyncTask.java:391)
05-17 18:24:57.069: ERROR/WindowManager(18850): at com.mypkg.myP.onCreate(viewP.java:94)
05-17 18:24:57.069: ERROR/WindowManager(18850): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
05-17 18:24:57.069: ERROR/WindowManager(18850): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2544)
05-17 18:24:57.069: ERROR/WindowManager(18850): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2621)
05-17 18:24:57.069: ERROR/WindowManager(18850): at android.app.ActivityThread.access$2200(ActivityThread.java:126)
05-17 18:24:57.069: ERROR/WindowManager(18850): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1932)
05-17 18:24:57.069: ERROR/WindowManager(18850): at android.os.Handler.dispatchMessage(Handler.java:99)
05-17 18:24:57.069: ERROR/WindowManager(18850): at android.os.Looper.loop(Looper.java:123)
05-17 18:24:57.069: ERROR/WindowManager(18850): at android.app.ActivityThread.main(ActivityThread.java:4595)
05-17 18:24:57.069: ERROR/WindowManager(18850): at java.lang.reflect.Method.invokeNative(Native Method)
05-17 18:24:57.069: ERROR/WindowManager(18850): at java.lang.reflect.Method.invoke(Method.java:521)
05-17 18:24:57.069: ERROR/WindowManager(18850): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
05-17 18:24:57.069: ERROR/WindowManager(18850): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
05-17 18:24:57.069: ERROR/WindowManager(18850): at dalvik.system.NativeStart.main(Native Method)
You're trying to show a Dialog after you've exited an Activity.
[EDIT]
This question is one of the top search on google for android developer, therefore Adding few important points from comments, which might be more helpful for future investigator without going in depth of comment conversation.
Answer 1 :
You're trying to show a Dialog after you've exited an Activity.
Answer 2
This error can be a little misleading in some circumstances (although the answer is still completely accurate) - i.e. in my case an unhandled Exception was thrown in an AsyncTask, which caused the Activity to shutdown, then an open progressdialog caused this Exception.. so the 'real' exception was a little earlier in the log
Answer 3
Call dismiss() on the Dialog instance you created before exiting your Activity, e.g. in onPause() or onDestroy()
The solution is to call dismiss()
on the Dialog
you created in viewP.java:183
before exiting the Activity
, e.g. in onPause()
. All Window
s&Dialog
s should be closed before leaving an Activity
.
If you are using AsyncTask
, probably that log message can be deceptive. If you look up in your log, you might find another error, probably one in your doInBackground()
method of your AsyncTask
, that is making your current Activity
to blow up, and thus once the AsyncTask
comes back.. well, you know the rest. Some other users already explained that here :-)
doInBackground
of the AsyncTask
class but without declare it in the AndroidManifest
file using the property android:name
like this: android:name="my.package.MyApplicationClass"
. A good practice when using AsyncTask
it is always remember to instantiate your alert inside the method onPreExecute
and dismissing it on onPostExecute
.
I triggered this error by mistakenly calling hide()
instead of dismiss()
on an AlertDialog
.
You can get this exception by just a simple/dumb mistake, by (for example) accidentally calling finish()
after having displayed an AlertDialog
, if you miss a break call statement in a switch statement...
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.new_button:
openMyAlertDialog();
break; <-- If you forget this the finish() method below
will be called while the dialog is showing!
case R.id.exit_button:
finish();
break;
}
}
The finish()
method will close the Activity
, but the AlertDialog
is still displaying!
So when you're staring intently at the code, looking for bad threading issues or complex coding and such, don't lose sight of the forest for the trees. Sometimes it can be just something as simple and dumb as a missing break statement. :)
The answers to this question were all correct, but a little confusing for me to actually understand why. After playing around for around 2 hours the reason to this error (in my case) hit me:
You already know, from reading other answers, that the has X has leaked window DecorView@d9e6131[]
error means a dialog was open when your app closed. But why?
It could be, that your app crashed for some other reason while your dialog was open
This lead to your app closing because of some bug in your code, which lead to the dialog remaining open at the same time as your app closed due to the other error.
https://i.stack.imgur.com/VCjhY.jpg
One error causes another, which causes another, like DOMINOS!
This problem arises when trying to show a Dialog after you've exited an Activity.
I just solved this problem just by writing down the following code:
@Override
public void onDestroy(){
super.onDestroy();
if ( progressDialog!=null && progressDialog.isShowing() ){
progressDialog.cancel();
}
}
Basically, from which class you started progressDialog, override onDestroy method and do this way. It solved "Activity has leaked window" problem.
I recently faced the same issue.
The reason behind this issue is that the activity being closed before the dialog is dismissed. There are various reasons for the above to happen. The ones mentioned in the posts above are also correct.
I got into a situation, because in the thread, I was calling a function which was throwing exception. Because of which the window was being dismissed and hence the exception.
This could help.
if (! isFinishing()) {
dialog.show();
}
Dismiss the dialog when activity destroy
@Override
protected void onDestroy()
{
super.onDestroy();
if (pDialog!=null && pDialog.isShowing()){
pDialog.dismiss();
}
}
I had the same obscure error message and had no idea why. Given clues from the previous answers, I changed my non-GUI calls to mDialog.finish() to be mDialog.dismiss() and the errors disappeared. This wasn't affecting my widget's behavior but it was disconcerting and could well have been flagging an important memory leak.
I was getting these logs in my video player application. These messages were thrown while the video player was closed. Interestingly, I used to get these logs once in a few runs in a random manner. Also my application does not involve in any progressdialog
. Finally, I got around this issue with the below implementation.
@Override
protected void onPause()
{
Log.v("MediaVideo", "onPause");
super.onPause();
this.mVideoView.pause();
this.mVideoView.setVisibility(View.GONE);
}
@Override
protected void onDestroy()
{
Log.v("MediaVideo", "onDestroy");
super.onDestroy();
}
@Override
protected void onResume()
{
Log.v("MediaVideo", "onResume");
super.onResume();
this.mVideoView.resume();
}
Override the OnPause
with call to mVideoView.pause()
and the set visibility
to GONE
. This way I could resolve the "Activity has leaked window
" log error issue.
I was having the same problem and found this page, and while my situation was different I called finish
from a if
block before it defined the alert box.
So, simply calling dismiss
wouldn't work (as it hasn't been made yet) but after reading Alex Volovoy's answer and realizing it was the alert box causing it. I tried to add a return statement right after the finish inside that if
block and that fixed the issue.
I thought once you called finish it stopped everything and finished right there, but it doesn't. It seem to go to the end of the block of code it's in then finishes.
So, if you want to implement a situation where sometimes it'll finish before doing some code you do gotta put a return statement right after the finish or it'll keep on going and and act like the finish was called at the end of the block of code not where you called it. Which is why I was getting all those weird errors.
private picked(File aDirectory){
if(aDirectory.length()==0){
setResult(RESULT_CANCELED, new Intent());
finish();
return;
}
AlertDialog.Builder alert= new AlertDialog.Builder(this); // Start dialog builder
alert
.setTitle("Question")
.setMessage("Do you want to open that file?"+aDirectory.getName());
alert
.setPositiveButton("OK", okButtonListener)
.setNegativeButton("Cancel", cancelButtonListener);
alert.show();
}
If you don't put the return right after I called finish in there, it will act as if you have called it after the alert.show();
and hence it would say that the window is leaked by finishing just after you made the dialog appear, even though that's not the case, it still think it is.
I thought I'd add this as here as this shows the finish command acted differently then I thought it did and I'd guess there are other people who think the same as I did before I discovered this.
This is not the answer to the question but it's relevant to the topic.
If the activity has defined an attribute in the Manifest
android:noHistory="true"
then after executing onPause(), the context of activity is lost. So all the view's using this context might give this error.
progessdialog.show()
.. and progressdialog.hide()
in asynctask
of the same activity instead of onPause()
from activity
?? have a look at my problem... stackoverflow.com/questions/39332880/…
Generally this issue occurs due to progress dialog : you can solve this by using any one of the following method in your activity:
// 1):
@Override
protected void onPause() {
super.onPause();
if ( yourProgressDialog!=null && yourProgressDialog.isShowing() )
{
yourProgressDialog.cancel();
}
}
// 2) :
@Override
protected void onDestroy() {
super.onDestroy();
if ( yourProgressDialog!=null && yourProgressDialog.isShowing()
{
yourProgressDialog.cancel();
}
}
here is a solution when you do want to dismiss AlertDialog but do not want to keep a reference to it inside activity.
solution requires you to have androidx.lifecycle dependency in your project (i believe at the moment of the comment it's a common requirement)
this lets you to delegate dialog's dismiss to external object (observer), and you dont need to care about it anymore, because it's auto-unsubscribed when activity dies. (here is proof: https://github.com/googlecodelabs/android-lifecycles/issues/5).
so, the observer keeps the reference to dialog, and activity keeps reference to observer. when "onPause" happens - observer dismisses the dialog, and when "onDestroy" happens - activity removes observer, so no leak happens (well, at least i dont see error in logcat anymore)
// observer
class DialogDismissLifecycleObserver( private var dialog: AlertDialog? ) : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun onPause() {
dialog?.dismiss()
dialog = null
}
}
// activity code
private fun showDialog() {
if( isDestroyed || isFinishing ) return
val dialog = AlertDialog
.Builder(this, R.style.DialogTheme)
// dialog setup skipped
.create()
lifecycle.addObserver( DialogDismissLifecycleObserver( dialog ) )
dialog.show()
}
Not only try to show an alert but it can also be invoked when you finish a particular instance of activity and try to start new activity/service or try to stop it.
Example:
OldActivity instance;
oncreate() {
instance=this;
}
instance.finish();
instance.startActivity(new Intent(ACTION_MAIN).setClass(instance, NewActivity.class));
Had the problem where I finished an Activity when a ProgressDialog was still shown.
So first hide the Dialog and then finish the activity.
Try this code:
public class Sample extends Activity(){
@Override
public void onCreate(Bundle instance){
}
@Override
public void onStop() {
super.onStop();
progressdialog.dismiss(); // try this
}
}
progressdialog.dismiss();
this can create NullPointerException.
This can be if you have an error at doInBackground()
function and have this code.
Try to add dialog at last. At first check and fix doInBackground()
function
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(CreateAccount.this);
pDialog.setMessage("Creating Product..");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
protected String doInBackground(String...args) {
ERROR CAN BE IS HERE
}
protected void onPostExecute(String file_url) {
// dismiss the dialog once done
pDialog.dismiss();
This happened to me when i am using ProgressDialog
in AsyncTask
. Actually i am using hide()
method in onPostExecute
. Based on the answer of @Alex Volovoy i need to use dismiss()
with ProgressDialog
to remove it in onPostExecute and its done.
progressDialog.hide(); // Don't use it, it gives error
progressDialog.dismiss(); // Use it
AsyncTask
and you show the Dialog
, then something happens which makes the Activity
call onPause()
(maybe some logic in your AsyncTask itself, like a listener, then it will leak. 2) As mentioned above, theDialog
which was created with that Activity
Context
is never dismissed and the Activity
moves on.
The "Activity has leaked window that was originally added...
" error occurs when you try show an alert after the Activity
is effectively finished
.
You have two options AFAIK:
Rethink the login of your alert: call dismiss() on the dialog before actually exiting your activity. Put the dialog in a different thread and run it on that thread (independent of the current activity).
You have to make Progressdialog
object in onPreExecute
method of AsyncTask
and you should dismiss
it on onPostExecute
method.
Best solution is just add dialog in try catch and dismiss dialog when exception occur
Just use below code
try {
dialog.show();
} catch (Exception e) {
dialog.dismiss();
}
dialog.dismiss()
will produce error too
Best solution is put this before showing progressbar
or progressDialog
if (getApplicationContext().getWindow().getDecorView().isShown()) {
//Show Your Progress Dialog
}
In my case, the reason was that I forgot to include a permission in the Android manifest file.
How did I find out? Well, just like @Bobby says in a comment beneath the accepted answer, just scroll further up to your logs and you'll see the first reason or event that really threw the Exception. Apparently, the message "Activity has leaked window that was originally added" is only an Exception that resulted from whatever the first Exception is.
Try below code , it will work any time you will dismiss the progress dialogue and it will see whether its instance is available or not.
try {
if (null != progressDialog && progressDialog.isShowing()) {
progressDialog.dismiss();
progressDialog = null;
}
} catch (Exception e) {
e.printStackTrace();
}
Window leaked exceptions have two reasons:
1) showing the dialog when Activity Context doesn't exists, to solve this you should show the dialog only you are sure Activity exists:
if(getActivity()!= null && !getActivity().isFinishing()){
Dialog.show();
}
2) not dismiss the dialog appropriately, to solve use this code:
@Override
public void onDestroy(){
super.onDestroy();
if ( Dialog!=null && Dialog.isShowing() ){
Dialog.dismiss();
}
}
I have another solution for this, and would like to know if it seems valid to you: instead of dismissing in the onDestroy, which seems to be the leading solution, I'm extending ProgressDialog...
public class MyProgressDialog extends ProgressDialog {
private boolean isDismissed;
public MyProgressDialog(Context context) {
super(context);
}
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
dismiss();
}
@Override
public void dismiss() {
if (isDismissed) {
return;
}
try {
super.dismiss();
} catch (IllegalArgumentException e) {
// ignore
}
isDismissed = true;
}
This is preferable, AFAIC, because you don't have to hold the progress dialog as a member, just fire(show) and forget
if (mActivity != null && !mActivity.isFinishing() && mProgressDialog != null && mProgressDialog.isShowing()) {
mProgressDialog.dismiss();
}
Success story sharing