【问题标题】:Android: "BadTokenException: Unable to add window; is your activity running?" at showing dialog in PreferenceActivityAndroid:“BadTokenException:无法添加窗口;您的活动正在运行吗?”在 PreferenceActivity 中显示对话框
【发布时间】:2011-11-16 22:02:59
【问题描述】:

我想寻求帮助:在我的应用程序中,我只有一个活动,PreferenceActivity(不需要其他活动,它只是一个简单的后台同步应用程序,所以 PrefsActivity 是主/启动器)。在用户设置首选项后,检查checkBoxPreference,然后启动(或停止)服务。开始时,会显示一个对话框。 但问题是:如果用户按下(离开活动),再次启动它,然后尝试检查checkBoxPref.,prefsactivity 崩溃。对话框不显示。我不知道为什么,以及如何解决它。

这段代码与那部分完全相同,是什么给了我问题:

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>

和清单:

<?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 错误:

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} 

在google了很多之后,我认为错误的部分是ProgressDialog dialog = new ProgressDialog(this);。导致this 发生变化。但是将其更改为getApplicationContext()PrefsActivity.this 并没有帮助,问题仍然存在。 请告诉我为什么会发生这种情况,以及可能的解决方案!谢谢! 我被卡住了,现在我不知道......

【问题讨论】:

  • 使用 getParent() 代替它并尝试
  • 检查此链接 [BadTokenException ](vinnysoft.blogspot.com/2010/11/…)。这将对您有所帮助。谢谢文奇。
  • 使用 getParent(),给我 NullpointerException。 :(
  • 感谢您的回答,我也找到了这个页面。但是仅在活动未完成时显示对话框并不是解决方案。 Activity处于运行状态,按下返回后重新启动。问题应该是(我认为)活动“改变”(改变了“this”引用),而不是它正在完成。
  • @Lama 在你改变了这个参考之后它现在可以工作了吗?

标签: android progressdialog preferenceactivity


【解决方案1】:

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

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

【讨论】:

  • 您不应将布尔值与另一个布尔值进行比较,而应使用布尔值! 运算符(或不使用)。
  • 是风格问题,而不是功能问题。两者在技术上是相同的,但是:stackoverflow.com/questions/2661110/…programmers.stackexchange.com/questions/136908/… 后者有一个我喜欢的答案:它更容易阅读,因为! 读作 not 并且 Java 标识符通常是英文-可读。
  • 感谢 Darkhogg 的链接。提出了一些好的观点。上面的答案示例已更改,我现在也将更改我的代码样式。
  • 这个转换为Activity 是多余的。
  • @Exception-al 对于第一个示例代码,Activity 强制转换是必需的,因为 mContext 被作为 Context 对象传递。但是,我认为您对第二个代码示例是正确的,因此我将其删除。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    if (!isFinishing()) {
        //showdialog here
        }
    

    【讨论】:

      【解决方案4】:

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

      • 永远不要将对话框声明/实例化为局部变量。
      • 制作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 的上下文已失效时会发生错误。

      【讨论】:

      • 您确定需要自己关闭对话框吗?活动的 android 代码似乎已经为您关闭它们:grepcode.com/file_/repository.grepcode.com/java/ext/…
      • 是的,这似乎是正确的。我通常处理由片段组成的代码库,所以我猜我在八月份写这篇文章时是为了片段。我会调查并更新帖子。
      【解决方案5】:

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

          // create alert dialog
          if (enableNetworkDialog == null || !enableNetworkDialog.isShowing())
              enableNetworkDialog = alertDialogBuilder.create();
          if (context instanceof AppCompatActivity && !((AppCompatActivity) context).isFinishing())
              enableNetworkDialog.show(); 
      

      【讨论】:

        【解决方案6】:

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

        【讨论】:

        • 正确的上下文是什么?应用上下文?
        猜你喜欢
        • 1970-01-01
        • 2015-05-27
        • 1970-01-01
        • 2017-05-31
        • 1970-01-01
        • 2019-01-03
        • 1970-01-01
        • 1970-01-01
        • 2014-10-22
        相关资源
        最近更新 更多