Android 1.6: "android.вид.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)
Я создаю его, позвонив showDialog
С кодом на дисплее. The 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 ответов
вместо :
Context appContext = this.getApplicationContext();
вы должны использовать указатель на действие, в котором вы находитесь (вероятно,this
).
меня сегодня тоже укусили, раздражающая часть-это getApplicationContext()
дословно от developer.android.com : (
вы не можете отобразить окно/диалог приложения через контекст, который не является действием. Попробуйте передать допустимую ссылку на действие
то же самое с getApplicationContext.
документы на сайте android говорят использовать его, но он не работает...грррр : - П
Так же:
dialog = new Dialog(this);
"этот" обычно это ваша деятельность, с которой вы начинаете диалог.
документы Android предлагают использовать getApplicationContext ();
но это не будет работать вместо того, чтобы использовать вашу текущую деятельность при создании экземпляра AlertDialog.Строитель или AlertDialog или диалог...
Ex:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
или
AlertDialog.Builder builder = new AlertDialog.Builder((Your Activity).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
, которого давно не существовало.
глупая глупая ошибка, тем более, что мне действительно не нужно было держать объект как static
в первую очередь...
просто измените его на
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);
}
это работает для меня !!
Как говорится, вам нужна активность в качестве контекста для диалога, используйте " YourActivity.это" для статического контекста или проверки здесь для того, как использовать динамический в безопасном режиме
попробуйте сбросить окна
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);
// }
});
}
текст здесь:-
используйте это для получения activity
контекст progressdialog
progressdialog = new ProgressDialog(Splash.this);
или progressdialog = new ProgressDialog(this);
использовать это для получения контекста приложения для BroadcastListener
не для progressdialog
.
progressdialog = new ProgressDialog(getApplicationContext());
progressdialog = new ProgressDialog(getBaseContext());
лучший и самый безопасный способ показать "ProgressDialog" в AsyncTask, избегая проблемы утечки памяти, - использовать "обработчик" с Looper.главный.)(
private ProgressDialog tProgressDialog;
затем в "onCreate"
tProgressDialog = new ProgressDialog(this);
tProgressDialog.setMessage(getString(R.string.loading));
tProgressDialog.setIndeterminate(true);
Теперь вы закончили с частью настройки. Теперь вызовите "showProgress ()" и "hideProgress ()" в AsyncTask.
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);
}