58

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...

4

6 回答 6

83

我有一个非常相似的问题(这让我来到了这里)并找到了一个非常简单的解决方法。虽然我的代码不同,但它应该很容易适应。这是我的修复:

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

因此,在问题的示例代码中,修复将是(猜测):

@Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
    if (key.equals("checkTest")) {
        if (! this.isFinishing()) {
            showDialog(1);
        }
    }
    if (key.equals("cancel")) {
        dismissDialog(1);
    }
}// onSPC
于 2012-07-05T08:04:46.660 回答
4

也许您没有关闭或取消注册活动中的某些内容。在这种情况下,请尝试在 onDestroy 上取消注册广播接收器。

于 2012-02-17T16:33:30.613 回答
3

这通常是由于您的应用程序尝试使用先前完成Activitycontext. 然后在显示对话框之前检查活动是否没有被其他一些应用程序或其他触发器关闭

if (!isFinishing()) {
    //showdialog here
    }
于 2019-01-18T05:18:15.180 回答
1

在将崩溃跟踪引入项目后,我注意到这个问题经常出现,并发现在整个项目中相同的修复程序可以消除崩溃:

  • 永远不要将对话框声明/实例化为局部变量。
  • 使 Activity 的所有 Dialogs 实例变量。
  • 覆盖 onDestroy 并调用 if(dialog != null) dialog.dismiss();

例子:

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();
    }
  }

错误消息说“无法添加窗口”具有误导性,因为我发现当您离开 Activity 并且传递给 Dialog 的上下文已失效时会发生错误。

于 2013-08-22T15:55:28.467 回答
1

对我来说,这解决了问题..检查对话框是否为空或不显示,如果是,则再次创建。

    // create alert dialog
    if (enableNetworkDialog == null || !enableNetworkDialog.isShowing())
        enableNetworkDialog = alertDialogBuilder.create();
    if (context instanceof AppCompatActivity && !((AppCompatActivity) context).isFinishing())
        enableNetworkDialog.show(); 
于 2017-10-03T10:45:40.583 回答
0

顶级解决方案只能防止崩溃。对我来说,问题是我提到了一个错误context来显示警报对话框。正确通过后context,问题就解决了。

于 2016-09-14T08:08:13.583 回答