282

我试图打开一个对话窗口,但每次我尝试打开它时都会抛出这个例外:

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变量看起来好像它正确地填充在调试器。

回答

597

相反的: Context appContext = this.getApplicationContext(); 你应该使用一个指向你(可能this)是活动的。

我得到今天这个被咬过,恼人的部分是getApplicationContext()是逐字从developer.android.com :(

+2

它也被报告为一个错误(虽然它不是当用户发布问题时):http://code.google.com/p/android/issues/detail?id=11199 – 2011-09-30 00:45:50

+61

只是以防万一这有助于任何人 - 在对话框中使用myActivity.this作为上下文。 – 2011-12-05 15:55:10

+13

这个问题和答案在2天内变成3岁。我仍然获得声望,所以我猜Google还没有修复他们的文档... – Torp 2013-04-12 17:50:36

75

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

+0

怎么样?我尝试了'activity.this'和'activity.getBaseContext()'但没有用。任何帮助? – Darpan 2014-10-15 11:44:36

+3

明白了。直接传递您的活动名称。没有'.this'。 – Darpan 2014-10-15 11:52:49

+0

Darpan,你确实解决了我的问题。 – Machado 2015-02-20 11:58:44

43

同上的getApplicationContext事情。

在Android网站上的文件说要使用它,但它不工作... grrrrr :-P

只要做到:

dialog = new Dialog(this); 

“这个”通常是您从其开始对话的活动。

12

我有一个类似的问题在那里我有另一个类是这样的:

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

39

Android的文件建议使用getApplicationContext();

但它不会工作,而不是使用您当前的活动,而实例化AlertDialog.Builder或AlertDialog或对话框...

例:

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

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

这大大帮助了我。我试图在另一个对话框中创建一个对话框,并且只有“AlertDialog.Builder(this);”发生了一个错误。谢谢! – EHarpham 2012-10-20 12:16:15

+0

(ActivityName.this)在尝试在onClick按钮中创建对话框时特别有用 – RmK 2014-12-16 11:51:42

+0

我的问题是我在适配器内部的AlertDialog内建立ProgressDialog ...我无法让它工作。 – santafebound 2017-07-06 19:22:41

12

只是把它变成

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

而不是

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

你也可以这样做

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

这对我有效!

2

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

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

使用的

mDialogBuilder = new AlertDialog.Builder(getApplicationContext); 

这种替代,而不是它的工作原理。

4

不要在声明的台词

始终使用this或您的activity.this

16

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

+0

这是正确的答案。 – Oussaki 2015-05-04 22:59:28

+0

这是正确的答案。 – user3687895 2015-05-11 15:28:11

9

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

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

这需要SYSTEM_ALERT_WINDOW权限:

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

由于文档说:

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

这是一个解决方案,只有在您需要一个未附加到活动的对话框时才应该使用。

+0

这是来自API级别26的现已弃用的标志。因为它允许开发人员使用系统窗口进行玩耍,这从用户角度来看并不好。 – CopsOnRoad 2018-01-19 06:51:13

3

这个工作对我 -

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

,因为它是说,你需要一个活动作为背景的对话框中,使用“YourActivity.this”为静态上下文或检查here如何使用在安全模式下

0

尝试一个动态到dialog窗口的类型重置为

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

不要忘记使用许可android.permission.SYSTEM_ALERT_WINDOW

0

最好和保险柜在AsyncTask中显示'ProgressDialog',避免内存泄漏问题的方法是在Looper.main()中使用'Handler'。

private ProgressDialog tProgressDialog; 

然后在 '的onCreate'

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

现在,您R中的设置部分完成。现在在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); 
    } 
相关问题