Android 1.6:“android.view.WindowManager $ BadTokenException:无法添加窗口 – 标记null不适用于应用程序”
我试图打开一个对话框窗口,但每次我试图打开它会引发这个异常:
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
变量好像正确地填充在调试器。
即这一行: Context appContext = this.getApplicationContext();
必须去,而是使用一个指向你所在的活动的指针(可能是这个)。
今天我也被这个咬了,讨厌的部分是getApplicationContext()
是逐字从developer.android.com 🙁
您不能通过不是活动的上下文显示应用程序窗口/对话框。 尝试传递有效的活动参考
同上getApplicationContext的东西。
在Android网站上的文件说要使用它,但它不工作… grrrrr 😛
做就是了:
dialog = new Dialog(this);
“this”通常是您从其开始对话的活动。
Android文档建议使用getApplicationContext();
但它不会工作,而不是使用您当前的活动,而实例化AlertDialog.Builder或AlertDialog或对话框…
例如:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
要么
AlertDialog.Builder builder = new AlertDialog.Builder((Your Activity).this);
而不是getApplicationContext()
,只需使用ActivityName.this
我有一个类似的问题,我有另一个类是这样的:
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
,这个Activity
不存在。
愚蠢的错误,特别是因为我真的不需要把对象固定在首位…
把它改成
AlertDialog.Builder alert_Categoryitem = new AlertDialog.Builder(YourActivity.this);
代替
AlertDialog.Builder alert_Categoryitem = new AlertDialog.Builder(getApplicationContext());
另一种解决方案是将窗口类型设置为系统对话框:
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
这需要SYSTEM_ALERT_WINDOW
权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
正如文件所说:
很少的应用程序应该使用此权限; 这些窗口用于与用户进行系统级的交互。
如果您需要一个没有附加到活动的对话框,则应该只使用这个解决方案。
不要使用getApplicationContext()
声明dialouge
总是使用this
或你的activity.this
这为我工作 –
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
对于嵌套对话框这个问题是非常普遍的,它工作的时候
AlertDialog.Builder mDialogBuilder = new AlertDialog.Builder(MyActivity.this);
被用来代替
mDialogBuilder = new AlertDialog.Builder(getApplicationContext);
这个选择。
你也可以做到这一点
public class Example extends Activity { final Context context = this; final Dialog dialog = new Dialog(context); }
这对我有效!
正如所说的,你需要一个Activity作为对话框的上下文,使用“YourActivity.this”作为静态上下文,或者在这里查看如何在安全模式下使用动态的
尝试重置dialog
窗口的类型
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT: dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
不要忘记使用权限android.permission.SYSTEM_ALERT_WINDOW
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
activity
上下文
progressdialog = new ProgressDialog(Splash.this);
或者progressdialog = new ProgressDialog(this);
使用它来获取BroadcastListener
应用程序上下文而不是progressdialog
。
progressdialog = new ProgressDialog(getApplicationContext()); progressdialog = new ProgressDialog(getBaseContext());
在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); }