首页 文章

Android 1.6:“android.view.WindowManager $ BadTokenException:无法添加窗口 - 令牌null不适用于应用程序”

提问于
浏览
293

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

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 变量似乎正确填充在调试器 .

16 回答

  • 0

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

    我今天也被这个咬了,令人讨厌的部分是 getApplicationContext() 是从developer.android.com逐字逐句:(

  • 45

    您无法通过非活动的上下文显示应用程序窗口/对话框 . 尝试传递有效的活动参考

  • 43

    同样关于getApplicationContext的事情 .

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

    做就是了:

    dialog = new Dialog(this);
    

    "this" 通常是您启动对话框的Activity .

  • 17

    Android文档建议使用getApplicationContext();

    但在实例化AlertDialog.Builder或AlertDialog或Dialog时,它将无法使用您当前的活动...

    例如:

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

    要么

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

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

  • 2

    我有一个类似的问题,我有另一个类这样的东西:

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

  • 78

    只需将其更改为

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

    代替

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

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

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

    这需要SYSTEM_ALERT_WINDOW权限:

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

    正如文档所说:

    很少有申请人应该使用此权限;这些窗口用于与用户进行系统级交互 .

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

  • 3

    在声明拨号时不要使用 getApplicationContext()

    始终使用 thisactivity.this

  • 12

    这对我有用 -

    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
    
  • 1

    对于嵌套对话框,这个问题很常见,它适用于何时

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

    用来代替

    mDialogBuilder = new AlertDialog.Builder(getApplicationContext);
    

    这种选择 .

  • 0

    你也可以这样做

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

    这对我有用!!

  • 0

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

  • 0

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

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

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

  • 608
    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);
    //                          }
            });
        }
    

    在这打字:-
    用它来获取 progressdialog 的上下文 progressdialog

    progressdialog = new ProgressDialog(Splash.this);
    

    progressdialog = new ProgressDialog(this);

    使用它来获取 BroadcastListener 的应用程序上下文而不是 progressdialog .

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

    在AsyncTask中显示'ProgressDialog',避免内存泄漏问题的最佳和最安全的方法是使用带有Looper.main()的'Handler' .

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

相关问题