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
С кодом на дисплее. Элемент 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 documents предлагает использовать 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);
Теперь вы r сделали с частью установки. Теперь вызовите ' 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); }