Android 1.6: „Android.view.WindowManager $ BadTokenException: Nie można dodać okna - token null nie jest przeznaczony dla aplikacji”

303

Próbuję otworzyć okno dialogowe, ale za każdym razem, gdy próbuję je otworzyć, zgłasza ten wyjątek:

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)

Tworzę go, dzwoniąc showDialogz identyfikatorem wyświetlacza. Program onCreateDialogobsługi rejestruje się poprawnie i mogę bez problemu przejść przez niego, ale załączyłem go, ponieważ wygląda na to, że czegoś mi brakuje:

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

Czy czegoś w tym brakuje? Niektóre pytania mówiły o tym problemie podczas tworzenia okna dialogowego onCreate, co dzieje się, ponieważ działanie nie zostało jeszcze utworzone, ale pochodzi ono z wywołania obiektu menu, a appContextzmienna wygląda na poprawnie wypełnioną w debuggerze.

Dan Monego
źródło

Odpowiedzi:

609

Zamiast: Context appContext = this.getApplicationContext(); powinieneś użyć wskaźnika do aktywności, w której jesteś (prawdopodobnie this).

Ugryzło mnie to również dzisiaj, denerwujące jest to, że getApplicationContext()jest dosłownie z developer.android.com :(

Torp
źródło
2
Jest również zgłaszany jako błąd (chociaż nie był to, gdy użytkownik opublikował pytanie): code.google.com/p/android/issues/detail?id=11199
Raymond Martineau
63
Na wypadek, gdyby to komukolwiek pomogło - użyj myActivity.this jako kontekstu w oknie dialogowym.
Rab Ross
13
To pytanie i odpowiedź kończy 3 lata w ciągu 2 dni. Wciąż otrzymuję reputację, więc myślę, że Google nadal nie naprawił swoich dokumentów ...
Torp
2
Zostało to naprawione w ( developer.android.com/guide/topics/ui/dialogs.html )
Martin Marconcini
6
Jest kwiecień 2016 r. I nadal ten wyjątek powoduje awarię aplikacji podczas inicjowania okna dialogowego.
Yogesh Seralia,
78

Nie można wyświetlić okna aplikacji / okna dialogowego przez kontekst, który nie jest działaniem. Spróbuj przekazać prawidłowe odwołanie do działania

Samuh
źródło
w jaki sposób? Próbowałem activity.thisi activity.getBaseContext()ale bezskutecznie. Jakaś pomoc?
Darpan
3
Rozumiem. Przekaż bezpośrednio nazwę swojej aktywności. Bez .this.
Darpan
45

To samo dotyczy sprawy getApplicationContext.

Dokumenty na stronie Androida mówią, aby z niego korzystać, ale to nie działa ... grrrrr :-P

Po prostu zrób:

dialog = new Dialog(this); 

„to” jest zazwyczaj Twoją Aktywnością, od której uruchamiasz okno dialogowe.

kenyee
źródło
43

Dokumenty Androida sugerują użycie getApplicationContext ();

ale nie będzie działać zamiast tego użyj bieżącej aktywności podczas tworzenia wystąpienia AlertDialog.Builder lub AlertDialog lub Dialog ...

Dawny:

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

lub

AlertDialog.Builder builder = new  AlertDialog.Builder((Your Activity).this);
Pradeep
źródło
To mi ogromnie pomogło. Próbowałem utworzyć okno dialogowe z innego okna dialogowego i po prostu miałem „AlertDialog.Builder (this);” dawał błąd. Dzięki!
EHarpham,
(ActivityName.this) jest szczególnie przydatny, gdy próbujesz utworzyć okno dialogowe wewnątrz
onKliknięcie
Mój problem polega na tym, że buduję ProgressDialog wewnątrz AlertDialog wewnątrz adaptera ... Nie mogę go uruchomić.
Martin Erlic,
17

Zamiast tego po getApplicationContext()prostu użyjActivityName.this

mahbub_siddique
źródło
13

Miałem podobny problem, gdy miałem inną klasę coś takiego:

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

Przez większość czasu działało dobrze, ale czasami występował błąd z tym samym błędem. Wtedy zdaję sobie sprawę, MyActivityże miałem ...

public class MyActivity extends Activity {
  public static Something something;

  public void someMethod() {
    if (something==null) {
      something=new Something(this);
    }
  }
}

Ponieważ trzymałem obiekt jako static, drugie uruchomienie kodu nadal zawierało oryginalną wersję obiektu, a zatem nadal odnosiło się do oryginałuActivity , którego już nie było.

Głupi, głupi błąd, zwłaszcza, że ​​tak naprawdę nie musiałem trzymać tego obiektu, tak jak staticw pierwszej kolejności ...

T.Hawk
źródło
12

Po prostu zmień na

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

Zamiast

AlertDialog.Builder alert_Categoryitem = 
    new AlertDialog.Builder(getApplicationContext());
Satheesh
źródło
9

Innym rozwiązaniem jest ustawienie typu okna na okno dialogowe systemu:

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

Wymaga to SYSTEM_ALERT_WINDOWpozwolenia:

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

Jak mówią doktorzy:

Bardzo niewiele aplikacji powinno korzystać z tego uprawnienia; te okna są przeznaczone do interakcji na poziomie systemu z użytkownikiem.

Jest to rozwiązanie, z którego należy korzystać tylko wtedy, gdy potrzebujesz okna dialogowego niepowiązanego z działaniem.

Anubian Noob
źródło
Jest to obecnie przestarzała flaga od poziomu API 26. Ponieważ pozwala programistom grać z oknem systemowym, co nie jest dobre z punktu widzenia użytkownika.
CopsOnRoad
4

Nie używaj getApplicationContext()przy deklarowaniu dialouge

Zawsze używaj thislub twójactivity.this

Jinu
źródło
2

W przypadku zagnieżdżonych okien dialogowych ten problem występuje bardzo często. Działa, gdy

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

jest używany zamiast

mDialogBuilder = new AlertDialog.Builder(getApplicationContext);

ta alternatywa.

Mifthi
źródło
2

To zadziałało dla mnie--

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

Posługiwać się

ActivityName.this
Suyog Gunjal
źródło
0

Możesz także to zrobić

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

To zadziałało dla mnie !!

Metalhead1247
źródło
0

Jak już powiedziano, potrzebujesz działania jako kontekstu dla okna dialogowego, użyj „YourActivity.this” dla kontekstu statycznego lub sprawdź tutaj, jak używać dynamicznego w trybie awaryjnym

Hugo
źródło
0

Spróbuj zresetować dialogtyp okna na

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

Nie zapomnij użyć pozwolenia android.permission.SYSTEM_ALERT_WINDOW

hopetribe
źródło
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);
//                          }
        });
    }

Tekst tutaj: -
użyj tego do uzyskania activitykontekstuprogressdialog

 progressdialog = new ProgressDialog(Splash.this);

lub progressdialog = new ProgressDialog(this);

użyj tego, aby uzyskać kontekst aplikacji dla BroadcastListener nie progressdialog.

progressdialog = new ProgressDialog(getApplicationContext());
progressdialog = new ProgressDialog(getBaseContext());
Faisal Ashraf
źródło
0

Najlepszym i najbezpieczniejszym sposobem pokazania „ProgressDialog” w AsyncTask, unikając problemu wycieku pamięci, jest użycie „Handler” z Looper.main ().

    private ProgressDialog tProgressDialog;

następnie w „onCreate”

    tProgressDialog = new ProgressDialog(this);
    tProgressDialog.setMessage(getString(R.string.loading));
    tProgressDialog.setIndeterminate(true);

Teraz skończyłeś z częścią instalacyjną. Teraz wywołaj „showProgress ()” i „hideProgress ()” w 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);
    }
Sankar Behera
źródło