代码之家  ›  专栏  ›  技术社区  ›  Dan Monego

android 1.6:“android.view.windowmanager$badTokenException:无法添加窗口-令牌空值不适用于应用程序”

  •  298
  • Dan Monego  · 技术社区  · 16 年前

    我正试图打开一个对话框窗口,但每次我试图打开它时,都会引发以下异常:

    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)
    

    我是通过打电话 showDialog 显示的ID。 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 变量似乎已在调试器中正确填充。

    16 回复  |  直到 8 年前
        1
  •  608
  •   CopsOnRoad    8 年前

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

    我今天也被这个咬了,最讨厌的是 getApplicationContext() 是developer.android.com的原话:(

        2
  •  78
  •   Samuh    16 年前

    不能通过非活动的上下文显示应用程序窗口/对话框。尝试传递有效的活动引用

        3
  •  45
  •   dakshbhatt21 czaku    12 年前

    在getApplicationContext上也是如此。

    Android网站上的文档说要使用它,但它不起作用…grrrr:-p

    只做:

    dialog = new Dialog(this); 
    

    “这个” 通常是启动对话框的活动。

        4
  •  43
  •   dakshbhatt21 czaku    12 年前

    Android文档建议使用getApplicationContext();

    但在实例化alertdialog.builder或alertdialog或dialog时,使用当前活动将无法替代…

    前任:

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

    AlertDialog.Builder builder = new  AlertDialog.Builder((Your Activity).this);
    
        5
  •  17
  •   mahbub_siddique    11 年前

    而不是 getApplicationContext() 只是使用 ActivityName.this

        6
  •  13
  •   T.Hawk    14 年前

    我有一个类似的问题,我有另一个类似的类:

    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 已经不存在了。

    愚蠢愚蠢的错误,尤其是当我真的不需要把物体当作 静止的 首先…

        7
  •  12
  •   JJD    12 年前

    把它改成

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

    而不是

    AlertDialog.Builder alert_Categoryitem = 
        new AlertDialog.Builder(getApplicationContext());
    
        8
  •  9
  •   Anubian Noob    10 年前

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

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

    这需要 SYSTEM_ALERT_WINDOW 许可:

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

    如医生所说:

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

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

        9
  •  4
  •   Jinu    11 年前

    不要使用 getApplicationContext() 关于宣布拨号

    总是使用 this 或者你的 activity.this

        10
  •  3
  •   Suyog Gunjal    10 年前

    这对我有用--

    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
    
        11
  •  2
  •   mifthi    11 年前

    对于嵌套对话框,此问题非常常见,在

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

    使用而不是

    mDialogBuilder = new AlertDialog.Builder(getApplicationContext);
    

    这种选择。

        12
  •  1
  •   JJD    12 年前

    你也可以这样做

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

    这对我有用!!

        13
  •  0
  •   Community Mohan Dere    9 年前

    如前所述,您需要一个活动作为对话的上下文,使用“youtractivity.this”作为静态上下文或检查 here 关于如何在安全模式下使用动态模式

        14
  •  0
  •   Uwe    9 年前

    尝试重置 dialog 窗口类型到

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

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

        15
  •  0
  •   rafsanahmad007    9 年前
    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 = new ProgressDialog(getApplicationContext());
    progressdialog = new ProgressDialog(getBaseContext());
    
        16
  •  0
  •   Sankar Behera    9 年前

    在异步任务中显示“ProgressDialog”的最佳和最安全的方法是将“handler”与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);
        }