【问题标题】:Android 1.6: "android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application"Android 1.6:“android.view.WindowManager$BadTokenException:无法添加窗口——令牌 null 不适用于应用程序”
【发布时间】:2011-02-07 18:21:02
【问题描述】:

我正在尝试打开一个对话窗口,但每次我尝试打开它时都会抛出此异常:

Uncaught handler: thread main exiting due to uncaught exception
android.view.WindowManager$BadTokenException: 
     Unable to add window -- token null is not for an application
  at android.view.ViewRoot.setView(ViewRoot.java:460)
  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
  at android.app.Dialog.show(Dialog.java:238)
  at android.app.Activity.showDialog(Activity.java:2413)

我通过使用显示器 ID 调用 showDialog 来创建它。 onCreateDialog 处理程序的日志很好,我可以毫无问题地单步执行它,但我已经附上了它,因为我似乎遗漏了一些东西:

@Override
public Dialog onCreateDialog(int id)
{
    Dialog dialog;
    Context appContext = this.getApplicationContext();
    switch(id)
    {
        case RENAME_DIALOG_ID:
            Log.i("Edit", "Creating rename dialog...");
            dialog = new Dialog(appContext);
            dialog.setContentView(R.layout.rename);
            dialog.setTitle("Rename " + noteName);
            break;
        default:
            dialog = null;
            break;
    }
    return dialog;      
}

这有什么遗漏吗?一些问题已经谈到在从onCreate 创建对话框时遇到此问题,这是因为尚未创建活动,但这是来自菜单对象的调用,appContext 变量似乎是在调试器中正确填充。

【问题讨论】:

    标签: android android-dialog runtimeexception android-windowmanager


    【解决方案1】:

    而不是: Context appContext = this.getApplicationContext(); 您应该使用指向您所在活动的指针(可能是this)。

    我今天也被这个咬了,烦人的部分是 getApplicationContext() 是来自 developer.android.com 的逐字记录:(

    【讨论】:

    • 它也被报告为一个错误(虽然不是在用户发布问题时):code.google.com/p/android/issues/detail?id=11199
    • 以防万一这对任何人都有帮助 - 使用 myActivity.this 作为对话框中的上下文。
    • 这个问答2天就满3岁了。我仍然获得声誉,所以我猜 Google 还没有修复他们的文档......
    • 这是 2016 年 4 月,但这个异常仍然导致应用程序在对话启动时崩溃。
    【解决方案2】:

    您不能通过不是 Activity 的 Context 显示应用程序窗口/对话框。尝试传递有效的活动参考

    【讨论】:

    • 怎么样?我试过activity.thisactivity.getBaseContext() 但无济于事。有什么帮助吗?
    • 知道了。直接在其中传递您的活动名称。没有.this
    【解决方案3】:

    getApplicationContext 也是如此。

    android网站上的文档说可以用,但是不行...grrrrr :-P

    只要做:

    dialog = new Dialog(this); 
    

    “this” 通常是您启动对话的 Activity。

    【讨论】:

      【解决方案4】:

      Android文档建议使用getApplicationContext();

      但它不会起作用,而是在实例化 AlertDialog.Builder 或 AlertDialog 或 Dialog 时使用您当前的活动......

      例如:

      AlertDialog.Builder builder = new  AlertDialog.Builder(this);
      

      AlertDialog.Builder builder = new  AlertDialog.Builder((Your Activity).this);
      

      【讨论】:

      • 这极大地帮助了我。我试图从另一个对话框中创建一个对话框,并且只有“AlertDialog.Builder(this);”给出了一个错误。谢谢!
      • (ActivityName.this) 在尝试在按钮的 onClick 内创建对话框时特别有用
      • 我的问题是我正在适配器内的 AlertDialog 内构建 ProgressDialog...我无法让它工作。
      【解决方案5】:

      不要使用getApplicationContext(),而是使用ActivityName.this

      【讨论】:

        【解决方案6】:

        我有一个类似的问题,我有另一个类似这样的课程:

        public class Something {
          MyActivity myActivity;
        
          public Something(MyActivity myActivity) {
            this.myActivity=myActivity;
          }
        
          public void someMethod() {
           .
           .
           AlertDialog.Builder builder = new AlertDialog.Builder(myActivity);
           .
           AlertDialog alert = builder.create();
           alert.show();
          }
        }
        

        大部分时间都运行良好,但有时它会因同样的错误而崩溃。然后我意识到在MyActivity 我有...

        public class MyActivity extends Activity {
          public static Something something;
        
          public void someMethod() {
            if (something==null) {
              something=new Something(this);
            }
          }
        }
        

        因为我将对象保存为static,所以第二次运行的代码仍然保存了对象的原始版本,因此仍然引用了不再存在的原始Activity

        愚蠢的错误,尤其是因为我真的不需要将对象作为static放在首位...

        【讨论】:

          【解决方案7】:

          改成

          AlertDialog.Builder alert_Categoryitem = 
              new AlertDialog.Builder(YourActivity.this);
          

          代替

          AlertDialog.Builder alert_Categoryitem = 
              new AlertDialog.Builder(getApplicationContext());
          

          【讨论】:

            【解决方案8】:

            另一种解决方法是将窗口类型设置为系统对话框:

            dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
            

            这需要SYSTEM_ALERT_WINDOW 权限:

            <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
            

            正如文档所说:

            很少有应用程序应该使用此权限;这些窗口旨在与用户进行系统级交互。

            只有在需要未附加到活动的对话框时才应使用此解决方案。

            【讨论】:

            • 这现在是 API 级别 26 的弃用标志。因为它允许开发人员使用从用户角度来看不好的系统窗口。
            【解决方案9】:

            不要在声明对话时使用getApplicationContext()

            始终使用this 或您的activity.this

            【讨论】:

              【解决方案10】:

              对于嵌套对话框,这个问题很常见,当

              AlertDialog.Builder mDialogBuilder = new AlertDialog.Builder(MyActivity.this);
              

              用来代替

              mDialogBuilder = new AlertDialog.Builder(getApplicationContext);
              

              这个选择。

              【讨论】:

                【解决方案11】:

                这对我有用--

                new AlertDialog.Builder(MainActivity.this)
                        .setMessage(Html.fromHtml("<b><i><u>Spread Knowledge Unto The Last</u></i></b>"))
                        .setCancelable(false)
                        .setPositiveButton("Dismiss",
                                new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog, int id) {
                                    }
                                }).show();
                

                使用

                ActivityName.this
                

                【讨论】:

                  【解决方案12】:

                  你也可以这样做

                  public class Example extends Activity {
                      final Context context = this;
                      final Dialog dialog = new Dialog(context);
                  }
                  

                  这对我有用!

                  【讨论】:

                    【解决方案13】:

                    如前所述,您需要一个 Activity 作为对话框的上下文,使用“YourActivity.this”作为静态上下文或查看here 了解如何在安全模式下使用动态上下文

                    【讨论】:

                      【解决方案14】:

                      尝试将dialog窗口的类型重置为

                      WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
                      dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
                      

                      别忘了使用权限android.permission.SYSTEM_ALERT_WINDOW

                      【讨论】:

                        【解决方案15】:
                        public class Splash extends Activity {
                        
                            Location location;
                            LocationManager locationManager;
                            LocationListener locationlistener;
                            ImageView image_view;
                            ublic static ProgressDialog progressdialog;
                            @Override
                            protected void onCreate(Bundle savedInstanceState) {
                                // TODO Auto-generated method stub
                                super.onCreate(savedInstanceState);
                                setContentView(R.layout.splash);
                                progressdialog = new ProgressDialog(Splash.this);
                                   image_view.setOnClickListener(new OnClickListener() {
                        
                                    @Override
                                    public void onClick(View v) {
                                        // TODO Auto-generated method stub
                        
                                                locationManager.requestLocationUpdates("gps", 100000, 1, locationlistener);
                                                Toast.makeText(getApplicationContext(), "Getting Location plz wait...", Toast.LENGTH_SHORT).show();
                        
                                                    progressdialog.setMessage("getting Location");
                                                    progressdialog.show();
                                                    Intent intent = new Intent(Splash.this,Show_LatLng.class);
                        //                          }
                                });
                            }
                        

                        这里的文字:-
                        使用它来获取activity 的上下文progressdialog

                         progressdialog = new ProgressDialog(Splash.this);
                        

                        progressdialog = new ProgressDialog(this);

                        使用它来获取BroadcastListener 的应用程序上下文 不适用于progressdialog

                        progressdialog = new ProgressDialog(getApplicationContext());
                        progressdialog = new ProgressDialog(getBaseContext());
                        

                        【讨论】:

                          【解决方案16】:

                          在 AsyncTask 中显示“ProgressDialog”,避免内存泄漏问题的最佳和最安全的方法是使用带有 Looper.main() 的“处理程序”。

                              private ProgressDialog tProgressDialog;
                          

                          然后在'onCreate'中

                              tProgressDialog = new ProgressDialog(this);
                              tProgressDialog.setMessage(getString(R.string.loading));
                              tProgressDialog.setIndeterminate(true);
                          

                          现在您已经完成了设置部分。现在在 AsyncTask 中调用“showProgress()”和“hideProgress()”。

                              private void showProgress(){
                                  new Handler(Looper.getMainLooper()){
                                      @Override
                                      public void handleMessage(Message msg) {
                                          tProgressDialog.show();
                                      }
                                  }.sendEmptyMessage(1);
                              }
                          
                              private void hideProgress(){
                                  new Handler(Looper.getMainLooper()){
                                      @Override
                                      public void handleMessage(Message msg) {
                                          tProgressDialog.dismiss();
                                      }
                                  }.sendEmptyMessage(1);
                              }
                          

                          【讨论】:

                            猜你喜欢
                            • 1970-01-01
                            • 1970-01-01
                            • 2012-09-12
                            • 1970-01-01
                            • 1970-01-01
                            • 2011-05-28
                            • 2019-01-04
                            • 2011-12-17
                            • 1970-01-01
                            相关资源
                            最近更新 更多