Android 1.6: «android.view.WindowManager $ BadTokenException: невозможно добавить окно - нулевой токен не для приложения»


303

Я пытаюсь открыть диалоговое окно, но каждый раз, когда я пытаюсь открыть его, оно выдает следующее исключение:

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переменная выглядит так, как будто она правильно заполнена в отладчике.

Ответы:


609

Вместо: Context appContext = this.getApplicationContext(); вы должны использовать указатель на активность, в которой вы находитесь (вероятно this).

Сегодня меня это тоже укусило, досадная часть getApplicationContext()- дословно от developer.android.com :(


2
Это также сообщается как ошибка (хотя это было не тогда, когда пользователь отправил вопрос): code.google.com/p/android/issues/detail?id=11199
Рэймонд Мартино,

63
На всякий случай это кому-нибудь поможет - используйте myActivity.this в качестве контекста в диалоге.
Раб Росс

13
Этот вопрос и ответ исполняется 3 года за 2 дня. Я до сих пор получаю репутацию, поэтому я думаю , Google до сих пор не фиксировали документы ...
Torp


6
Это апрель 2016 года, и это исключение вызывает сбой приложения при запуске диалога.
Йогеш Сералия

78

Вы не можете отобразить окно / диалог приложения через Контекст, который не является Деятельностью. Попробуйте передать действительную ссылку на активность


как? Я попробовал activity.thisи , activity.getBaseContext()но безрезультатно. Любая помощь?
Дарпан

3
Понял. Напишите в нем название вашей деятельности. Без .this.
Дарпан

45

То же самое с вещью getApplicationContext.

Документы на сайте Android говорят, что использовать его, но он не работает ... grrrrr :-P

Просто сделать:

dialog = new Dialog(this); 

«this» - это обычно ваша активность, с которой вы начинаете диалог.


43

Документы Android предлагают использовать getApplicationContext ();

но он не будет работать вместо того, чтобы использовать текущую активность при создании экземпляра AlertDialog.Builder или AlertDialog или Dialog ...

Пример:

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

или

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

Это очень помогло мне. Я пытался создать диалог из другого диалога и просто "AlertDialog.Builder (this);" давал ошибку. Спасибо!
EHarpham

(ActivityName.this) особенно полезно при попытке создать диалог внутри onClick кнопки
RmK

Моя проблема в том, что я создаю ProgressDialog внутри AlertDialog внутри адаптера ... Я не могу заставить его работать.
Мартин Эрлик


13

У меня была похожая проблема, где у меня был другой класс, примерно такой:

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прежде всего ...


12

Просто измените это на

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

Вместо того

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

9

Другое решение состоит в том, чтобы установить тип окна для системного диалога:

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

Это требует SYSTEM_ALERT_WINDOWразрешения:

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

Как говорят в документах:

Очень немногие приложения должны использовать это разрешение; Эти окна предназначены для взаимодействия на уровне системы с пользователем.

Это решение, которое вы должны использовать, только если вам требуется диалоговое окно, которое не привязано к действию.


Теперь этот флаг устарел на уровне API 26. Поскольку он позволяет разработчику играть с системным окном, что плохо с точки зрения пользователя.
CopsOnRoad

4

Не используйте getApplicationContext()при объявлении Dialouge

Всегда используйте thisили вашactivity.this


2

Для вложенных диалогов эта проблема очень распространена, она работает, когда

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

используется вместо

mDialogBuilder = new AlertDialog.Builder(getApplicationContext);

эта альтернатива.


2

Это сработало для меня

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 Example extends Activity {
    final Context context = this;
    final Dialog dialog = new Dialog(context);
}

Это сработало для меня!


0

Как уже говорилось, вам нужен Activity в качестве контекста для диалога, используйте «YourActivity.this» для статического контекста или проверьте здесь, как использовать динамический контекст в безопасном режиме.


0

Попробуйте сбросить dialogтип окна на

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

Не забудьте использовать разрешение android.permission.SYSTEM_ALERT_WINDOW


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

Лучший и самый безопасный способ показать «ProgressDialog» в AsyncTask, избегая проблемы утечки памяти, - это использовать «Обработчик» с Looper.main ().

    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);
    }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.