57

I'd like to ask for some help: In my app, I have only one activity, a PreferenceActivity (don't need other, it's just a simple background-sync app, so the PrefsActivity is the Main/Launcher). After the user setup preferences, checks a checkBoxPreference, and that starts (or stops) a service. At starting, a dialog shows. But here is the problem: if the user press back (leave the activity), start it again, and than tries to check the checkBoxPref., the prefsactivity crashes. Dialog doesn't shows. I have no idea why, and how to fix it.

This code is exactly same with that part, what gives me the problem:

PrefsActivity.java:

   package is.it.works;

   // imports .....

   public class PrefsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {
SharedPreferences prefs;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.prefs);
    prefs = PreferenceManager.getDefaultSharedPreferences(this);
    prefs.registerOnSharedPreferenceChangeListener(this);
}// onCreate

@Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
    if (key.equals("checkTest")) {
        showDialog(1);
    }
    if (key.equals("cancel")) {
        dismissDialog(1);
    }
}// onSPC

@Override
protected Dialog onCreateDialog(int id) {
    switch (id) {
    case 1: {
        ProgressDialog dialog = new ProgressDialog(this);
        dialog.setMessage("press back twice, start the app again, and click checkbox...");
        dialog.setIndeterminate(true);
        dialog.setCancelable(true);
        dialog.setOnCancelListener(new OnCancelListener() {

            @Override
            public void onCancel(DialogInterface dialog) {
                prefs.edit().putBoolean("cancel", false).commit();
            }
        });
        return dialog;
    }// case
    }// switch
    return null;
}// onCreateDialog
}// PrefsActivity

prefs.xml:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

    <CheckBoxPreference android:key="checkTest" android:title="test" />

</PreferenceScreen>

and the manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="is.it.works" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="4" />

<application android:icon="@drawable/icon" android:label="@string/app_name">
    <activity android:name=".PrefsActivity" android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

</application>
</manifest>

LogCat error:

09-14 10:34:34.472: ERROR/AndroidRuntime(281): Uncaught handler: thread main exiting due to uncaught exception
09-14 10:34:34.502: ERROR/AndroidRuntime(281): android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@43756de8 is not valid; is your activity running?
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.view.ViewRoot.setView(ViewRoot.java:456)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.view.Window$LocalWindowManager.addView(Window.java:409)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.app.Dialog.show(Dialog.java:238)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.app.Activity.showDialog(Activity.java:2413)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at is.it.works.PrefsActivity.onSharedPreferenceChanged(PrefsActivity.java:27)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.app.ApplicationContext$SharedPreferencesImpl$EditorImpl.commit(ApplicationContext.java:2727)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.preference.Preference.tryCommit(Preference.java:1199)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.preference.Preference.persistBoolean(Preference.java:1404)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.preference.CheckBoxPreference.setChecked(CheckBoxPreference.java:155)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.preference.CheckBoxPreference.onClick(CheckBoxPreference.java:143)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.preference.Preference.performClick(Preference.java:811)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.preference.PreferenceScreen.onItemClick(PreferenceScreen.java:190)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.widget.AdapterView.performItemClick(AdapterView.java:284)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.widget.ListView.performItemClick(ListView.java:3246)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.widget.AbsListView$PerformClick.run(AbsListView.java:1635)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.os.Handler.handleCallback(Handler.java:587)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.os.Handler.dispatchMessage(Handler.java:92)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.os.Looper.loop(Looper.java:123)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.app.ActivityThread.main(ActivityThread.java:4203)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at java.lang.reflect.Method.invokeNative(Native Method)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at java.lang.reflect.Method.invoke(Method.java:521)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at dalvik.system.NativeStart.main(Native Method)
09-14 10:34:34.522: INFO/Process(52): Sending signal. PID: 281 SIG: 3
09-14 10:34:34.532: INFO/dalvikvm(281): threadid=7: reacting to signal 3
09-14 10:34:34.592: INFO/dalvikvm(281): Wrote stack trace to '/data/anr/traces.txt'
09-14 10:34:38.533: DEBUG/dalvikvm(107): GC freed 437 objects / 21560 bytes in 136ms
09-14 10:34:39.183: INFO/global(175): Default buffer size used in BufferedReader constructor. It would be better to be explicit if an 8k-char buffer is required.
09-14 10:34:44.632: INFO/global(175): Default buffer size used in BufferedReader constructor. It would be better to be explicit if an 8k-char buffer is required.
09-14 10:34:47.412: INFO/Process(281): Sending signal. PID: 281 SIG: 9
09-14 10:34:47.472: INFO/ActivityManager(52): Process is.it.works (pid 281) has died.
09-14 10:34:47.492: INFO/WindowManager(52): WIN DEATH: Window{4394f638 is.it.works/is.it.works.PrefsActivity paused=false} 

After googleing a lot, I think, the wrong part is the ProgressDialog dialog = new ProgressDialog(this);. Cause this changes. But changing it to getApplicationContext(), or PrefsActivity.this doesn't help, the problem is still there. Please, tell me why is this happening, and what could be the solution! Thank You! I'm stuck, and now I have no idea...

Bugs Happen
  • 1,835
  • 4
  • 25
  • 50
Lama
  • 1,293
  • 3
  • 11
  • 10
  • 4
    use getParent() in place of this and try – Abhi Sep 14 '11 at 10:47
  • 1
    useing getParent(), gives me NullpointerException. :( – Lama Sep 14 '11 at 11:04
  • 4
    Check this link [BadTokenException ](http://vinnysoft.blogspot.com/2010/11/androidviewwindowmanagerbadtokenexcepti.html). This will help you. Thanks Venky. – Venky Sep 14 '11 at 11:00
  • Thanks for answer, I found this page too. But showing dialog just when activity isn't finishing is not the solution. The activity is in running state, after press back and start again. The problem sould be that (I think) the activity "changes" (changed "this" reference), not that it is in finishing. – Lama Sep 14 '11 at 11:11
  • @Lama Is it working now after u changed from this reference? – Venky Sep 14 '11 at 11:16
  • No, it isn't. That's the problem. (but I just think the reference changes, and that cause the error, I'm not sure, that's why I post this question) – Lama Sep 14 '11 at 11:37
  • ...and if that case is right, I don't know how to fix that problem. – Lama Sep 14 '11 at 12:30
  • Try to put log messages in the lifecycle methods of an activity. You will see that on press of back button, if you are in any activity then onDestroy method should be called. That is the reason that exception occurs and you will need to check if the activity is actually finished or is running. There is a diff when you press back button and home button. Try with both of them and see the diff. – sunil Oct 07 '11 at 12:23
  • Possible duplicate of [Unable to add window -- token android.os.BinderProxy is not valid; is your activity running?](https://stackoverflow.com/questions/9529504/unable-to-add-window-token-android-os-binderproxy-is-not-valid-is-your-activ) – Pod Sep 22 '17 at 10:51

6 Answers6

82

I had a very similar issue (which landed me here) and found a very simple fix for it. While my code is different, it should be easy to adapt. Here is my fix:

public void showBox() {
    mActive = true;
    if (! ((Activity) mContext).isFinishing()) {
        mDialogBox.show();
    }
} 

So, in the sample code in the question, the fix would have been (at a guess):

@Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
    if (key.equals("checkTest")) {
        if (! this.isFinishing()) {
            showDialog(1);
        }
    }
    if (key.equals("cancel")) {
        dismissDialog(1);
    }
}// onSPC
Tigger
  • 8,307
  • 4
  • 32
  • 38
  • 2
    You should not compare a boolean with another boolean, but use the boolean `!` operator (or nothing) instead. – Darkhogg Feb 12 '13 at 11:37
  • According to the [Android docs](http://developer.android.com/reference/android/app/Activity.html#isFinishing()) - `isFinishing()` returns either `true` or `false`. After a bit of research as to when it is correct to use `if (! boolean)` or `if (boolean == false)`, I failed to turn up anything definite. Do you have a link or something I can cross-check to back up your statement? – Tigger Feb 12 '13 at 23:46
  • 9
    Is a matter of style, not functionality. Both are technically the same, but: http://stackoverflow.com/questions/2661110/is-it-bad-to-explicitly-compare-against-boolean-constants-e-g-if-b-false-i http://programmers.stackexchange.com/questions/136908/why-use-boolean-variable-over-boolean-variable-false The latter has an answer that I like: It is easier to read, as in `!` reads as *not* and Java identifiers usually are english-readable. – Darkhogg Feb 13 '13 at 10:00
  • 1
    Thanks for the links Darkhogg. Some good points are raised. The answer example above has been changed and I'll also be changing my code style now. – Tigger Feb 13 '13 at 22:56
  • 1
    This cast to `Activity` is redundant. – Androiderson Sep 16 '13 at 13:37
  • 1
    @Exception-al For the first sample code the `Activity` cast was required as `mContext` was being passed as a `Context` object. However, I think you are correct for the second code sample, so I removed it. – Tigger Sep 17 '13 at 00:55
4

Maybe you didn't close or unregister something in your activity. In that case, try unregistering the broadcastreceiver on onDestroy.

Peter O.
  • 28,965
  • 14
  • 72
  • 87
yoryo
  • 51
  • 2
2

This is usually caused by your app trying to display a dialog using a previously-finished Activity as a context. Then check that the activity is not closed by some other apps or other triggers before showing the dialog

if (!isFinishing()) {
    //showdialog here
    }
MJ Montes
  • 2,491
  • 1
  • 9
  • 18
1

After introducing crash tracking to a project, I noticed this issue popping up quite frequently and found the same fix worked throughout the project to eliminate the crash:

  • Never declare/instantiate Dialogs as local variables.
  • Make all Dialogs instance variables of the Activity.
  • Override onDestroy and call if(dialog != null) dialog.dismiss();

Example:

MyActivity extends Activity {
  ProgressDialog mProgressDialog;
  AlertDialog mAlertDialog;


  @Override
  public void onCreate(Bundle savedInstanceState) {
    mProgressDialog = new ProgressDialog(MyActivity.this);
    mAlertDialog = new AlertDialog.Builder(MyActivity.this).show();
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    if(mProgressDialog != null) {
      mProgressDialog.dismiss();
    }
    if(mAlertDialog != null) {
      mAlertDialog.dismiss();
    }
  }

It is misleading that the error message says "unable to add window" as I've found the error happens when you are leaving an Activity and the context that was passed to your Dialog is dead.

Brendan Weinstein
  • 6,382
  • 6
  • 22
  • 29
  • are you sure you need to dismiss the dialogs yourself? the code of android for the activity seem already closes them for you : http://grepcode.com/file_/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/app/Activity.java/?v=source – android developer Nov 07 '13 at 14:58
  • Yes, this appears to be correct. I usually work on codebases made up of fragments, so I am guessing I meant this post for fragments when I wrote it back in August. I'll look into it and update the post. – Brendan Weinstein Nov 09 '13 at 20:00
1

For me this solved the problem.. checking if the dialog is null or not showing and if yes then create again.

    // create alert dialog
    if (enableNetworkDialog == null || !enableNetworkDialog.isShowing())
        enableNetworkDialog = alertDialogBuilder.create();
    if (context instanceof AppCompatActivity && !((AppCompatActivity) context).isFinishing())
        enableNetworkDialog.show(); 
Amit Tumkur
  • 2,437
  • 23
  • 27
0

The top solution only prevents the crash. For me the problem was that I had referred a wrong context to show the alert dialog. After passing the correct context, the problem was solved.

TharakaNirmana
  • 9,667
  • 8
  • 45
  • 67