Pein
Pein

Reputation: 1079

android illegal exception when dialog is showing

I have crash log:

java.lang.IllegalArgumentException: View=com.android.internal.policy.impl.PhoneWindow$DecorView{21f9ba68 V.E..... R.....ID 0,0-1136,402} not attached to window manager
at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:402)
at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:328)
at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:84)
at android.app.Dialog.dismissDialog(Dialog.java:433)
at android.app.Dialog.dismiss(Dialog.java:416)
at ys.a(ConfirmationDialog.java:82)
at ys.a(ConfirmationDialog.java:76)
at **com.smarttech.kapp.SnapshotActivity.onOptionsItemSelected(SnapshotActivity.java:147)**
at android.app.Activity.onMenuItemSelected(Activity.java:3036)
at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:373)
at com.android.internal.policy.impl.PhoneWindow.onMenuItemSelected(PhoneWindow.java:1222)
at com.android.internal.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:761)
at com.android.internal.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:155)
at com.android.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:904)
at com.android.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:894)
at android.widget.ActionMenuView.invokeItem(ActionMenuView.java:611)
at com.android.internal.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java:197)
at android.view.View.performClick(View.java:5217)
at android.view.View.onKeyUp(View.java:9663)
at android.widget.TextView.onKeyUp(TextView.java:7047)
at android.view.KeyEvent.dispatch(KeyEvent.java:3171)
at android.view.View.dispatchKeyEvent(View.java:8876)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1695)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1695)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1695)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1695)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1695)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.java:2671)
at com.android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1787)
at android.app.Activity.dispatchKeyEvent(Activity.java:2837)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2549)
at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:4661)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4616)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4174)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4227)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4193)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4303)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4201)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4360)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4174)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4227)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4193)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4201)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4174)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4227)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4193)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4336)
at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:4500)
at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:2607)
at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:2201)
at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:2192)
at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:2584)
at android.view.InputEventSender.dispatchInputEventFinished(InputEventSender.java:141)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:143)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:6117)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)

This is soruce code of showing dialog in snapshot activity:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            finish();
            return true;
        case R.id.snapshot_delete:
            Log.d(TAG, "delete snapshot");
            **delete();**
            return true;
        case R.id.snapshot_share:
            export();
            return true;
    }

    return super.onOptionsItemSelected(item);
}

private void delete() {
    Log.d(TAG, "Delete snapshot");
    final int index = pager.getCurrentItem();
    ConfirmationDialog.prompt(this, R.string.delete_snapshot, R.string.delete_snapshot_confirmation, R.string.delete, android.R.string.cancel, new Runnable() {
        @Override
        public void run() {
            snapshots.get(index).delete();
            loadSnapshots();
        }
    });
}

This crash is very hard to reproduce and it is all information what I have. What is a reason of this exception? And How it can be fixed? I think the reason is thread in dialog, but I'm not sure

public static void prompt(final Context context, int titleResourceId, int questionResourceId, int positiveButton, int negativeButton, final Runnable confirmedRunnable, final Runnable cancelledRunnable) {
    closeDialog();
    DialogInterface.OnClickListener confirmed = new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            currentDialog = null;
            confirmedRunnable.run();
        }
    };
    DialogInterface.OnClickListener cancelled = new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            currentDialog = null;
            if (cancelledRunnable != null) {
                cancelledRunnable.run();
            }
        };
    };
    currentDialog = new AlertDialog.Builder(context).setTitle(titleResourceId).setMessage(questionResourceId).setIcon(android.R.drawable.ic_dialog_alert).setPositiveButton(positiveButton, confirmed)
            .setNegativeButton(negativeButton, cancelled).show();
    currentDialog.setCancelable(cancelled == null);
    currentDialog.setCanceledOnTouchOutside(cancelled == null);
}

This is promt implementation

Upvotes: 19

Views: 19620

Answers (6)

ByteWelder
ByteWelder

Reputation: 5604

The top level of your stacktrace is telling you what is wrong:

java.lang.IllegalArgumentException: View=com.android.internal.policy.impl.PhoneWindow$DecorView{21f9ba68 V.E..... R.....ID 0,0-1136,402} not attached to window manager
at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:402)
at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:328)
at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:84)
at android.app.Dialog.dismissDialog(Dialog.java:433)
at android.app.Dialog.dismiss(Dialog.java:416)

You are calling dismiss on a dialog that is currently not being shown anymore. As in: your Activity/Fragment is possibly already destroyed when you call dismiss (-> "not attached to window manager").

[edit] One way to fix this is to check for activity.isFinishing() or fragment.isAdded()

Upvotes: 22

user6930148
user6930148

Reputation:

I have Same Issue, and I sove this Issue by checking:

if (alertDialog  != null && alertDialog .isShowing() && !this.isFinishing())
 {
  alertDialog .dismiss();
 }

Upvotes: 1

Axay Coolmoco
Axay Coolmoco

Reputation: 63

I suggest, you should also check if activity is not null.

if (activity != null && progressDialog != null && progressDialog.isShowing()) {
                progressDialog.dismiss();
            }

Upvotes: 0

Bjørn Stenfeldt
Bjørn Stenfeldt

Reputation: 1602

I see no reason why the entire app should crash over something like this. It appears to me that an exception at this point must be the result of the activity already having ended or something. In either case I'm guessing the user isn't looking at the dialog any longer, so I've made simple utility for closing my dialogs silently.

import android.app.Dialog;
import android.util.Log;

import java.io.PrintWriter;
import java.io.StringWriter;

public class DialogUtil {

    public static final String TAG = "DialogUtil";

    public static void safeDismiss(Dialog dialog) {
        if (dialog != null && dialog.isShowing()) {
            try {
                dialog.dismiss();
            } catch (RuntimeException ex) {
                StringWriter sw = new StringWriter();
                ex.printStackTrace(new PrintWriter(sw));
                Log.e(TAG, sw.toString());
            }
        }
    }
}

Upvotes: 1

Prashanth Debbadwar
Prashanth Debbadwar

Reputation: 1047

Please dismiss as follows

if ((alertDialog != null) && alertDialog.isShowing())
        {
            alertDialog.dismiss();
        }

Upvotes: 4

degs
degs

Reputation: 1072

A simple way to safely dismiss your dialog is to check if the view the Dialog is contained within is currently showing before attempting to dismiss it. This looks like:

if (view.isShown()) {
    dialog.dismiss()
}

Upvotes: 1

Related Questions