PopupWindow $ BadTokenException: nie można dodać okna - wartość null tokenu jest nieprawidłowa

80

Mam następujący błąd podczas wyświetlania PopupWindow. Błędy wywoływane są linią:

checkInPopup.showAtLocation((ViewGroup) mapView.getParent(), Gravity.CENTER_HORIZONTAL, 0, 0);

mapView jest MapView i nic nie jest null. Śledzenie stosu:

01-08 18:00:09.402: E/AndroidRuntime(27768): Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
01-08 18:00:09.402: E/AndroidRuntime(27768):    at android.view.ViewRootImpl.setView(ViewRootImpl.java:513)
01-08 18:00:09.402: E/AndroidRuntime(27768):    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:301)
01-08 18:00:09.402: E/AndroidRuntime(27768):    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:215)
01-08 18:00:09.402: E/AndroidRuntime(27768):    at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:140)
01-08 18:00:09.402: E/AndroidRuntime(27768):    at android.view.Window$LocalWindowManager.addView(Window.java:537)
01-08 18:00:09.402: E/AndroidRuntime(27768):    at android.widget.PopupWindow.invokePopup(PopupWindow.java:988)
01-08 18:00:09.402: E/AndroidRuntime(27768):    at android.widget.PopupWindow.showAtLocation(PopupWindow.java:845)
01-08 18:00:09.402: E/AndroidRuntime(27768):    at android.widget.PopupWindow.showAtLocation(PopupWindow.java:809)
01-08 18:00:09.402: E/AndroidRuntime(27768):    at com.geoloc.ActivityCheckIn.onCreate(ActivityCheckIn.java:50)
01-08 18:00:09.402: E/AndroidRuntime(27768):    at android.app.Activity.performCreate(Activity.java:4465)
01-08 18:00:09.402: E/AndroidRuntime(27768):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)

To jest kod z mojej aktywności (który rozszerza MapActivity)

    protected void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    setContentView(R.layout.checkin);
    mapView = (MapView) findViewById(R.id.mapview);

    LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    checkInPopup = new PopupWindow(inflater.inflate(CHECK_IN_POPUP_LAYOUT, null, false));
    checkInPopup.setOutsideTouchable(true);
    checkInPopup.setHeight(100);
    checkInPopup.setWidth(200);
    checkInPopup.showAtLocation((ViewGroup) mapView.getParent(), Gravity.CENTER_HORIZONTAL, 0, 0);
}

Dziękuję ci, że wyraziłeś swoje zdanie

znat
źródło

Odpowiedzi:

71

wyświetlasz wyskakujące okienko zbyt wcześnie. Możesz opublikować opóźnione uruchamianie w celu pokazania lokalizacji w Onresume, spróbuj

Edycja: ten post wydaje się mieć ten sam problem, w którym rozwiązano problemy z tworzeniem wyskakującego okienka w działaniu Androida

nandeesh
źródło
Sugerowałbym wyłapanie wyjątku i kontynuowanie ponownego publikowania ze znacznym opóźnieniem (przynajmniej kilka razy), ponieważ początkowego opóźnienia nie można przewidzieć.
Harsh
93

Ten sam problem zdarzył się ze mną, gdy próbuję wyświetlić menu podręczne w działaniu. Mam również to samo wykluczenie, ale napotykam problem n rozwiązany przez podanie kontekstu

YourActivityName.this zamiast getApplicationContext()na

Dialog dialog = new Dialog(getApplicationContext());

i tak to zadziałało dla mnie, może pomoże komuś innemu

Android jest dla mnie wszystkim
źródło
To mi dobrze pomogło. Dobra odpowiedź dzięki
Tharusha
34

Posługiwać się:

YourActivityName.this

Zamiast:

getApplicationContext();
Mian Taimoor Tahir
źródło
1
Tak, to działa w przypadku: nowego ProgressDialog (YourActivityName.this);
Lotfi
10

Istnieją dwa scenariusze, w których może wystąpić ten wyjątek. O jednym wspomina nandeesh. Inny scenariusz jest tutaj wymieniony: http://blackriver.to/2012/08/android-annoying-exception-unable-to-add-window-is-your-activity-running/

Upewnij się, że obsługujesz oba z nich

TheMan
źródło
7
Należy pamiętać, że odradza się udzielanie odpowiedzi zawierających tylko łącza, a odniesienia z czasem stają się nieaktualne. Rozważ dodanie tutaj samodzielnego streszczenia, zachowując link jako odniesienie.
kleopatra
@TheMan Nice ~ tak mała, potężna wskazówka! Dziękuję Ci!
cmcromance
5
  @Override
protected void onCreate(Bundle savedInstanceState) {
    View view = LayoutInflater.from(mContext).inflate(R.layout.popup_window_layout, new LinearLayout(mContext), true);
    popupWindow = new PopupWindow(view, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    popupWindow.setContentView(view);
}

   @Override
public void onWindowFocusChanged(boolean hasFocus) {
    if (hasFocus) {
        popupWindow.showAtLocation(parentView, Gravity.BOTTOM, 0, 0);
    }
}

prawidłowy sposób to popupwindow.show () w onWindowFocusChanged ().

Wow Chong
źródło
To rozwiązuje problem pierwotnego pytania i jest najlepszym / najczystszym rozwiązaniem.
Dale
3

Rodzic wyskakującego okienka nie może sam być wyskakującym okienkiem. Oboje ich rodzice muszą być tacy sami. Tak więc, jeśli tworzysz wyskakujące okienko w wyskakującym okienku, musisz zapisać wyskakujące okienko rodzica i uczynić je rodzicem.

oto przykład

Md Kauser Ahmmed
źródło
1

Spróbuj pokazać pop jak poniżej

findViewById(R.id.main_layout).post(new Runnable() {
        public void run() {
            mPopupWindow.showAtLocation(findViewById(R.id.main_layout), Gravity.CENTER, 0, 0);
            Button close = (Button) customView.findViewById(R.id.btn_ok);
            close.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mPopupWindow.dismiss();
                    doOtherStuff();
                }
            });
        }
    });
Gyanendra Singh
źródło
1

użyj tej metody przed pokazem

public static ViewGroup getActivityFirstLayout(Context ctx)
{
    return (ViewGroup)((ViewGroup) ActivityMaster.getActivity(ctx).findViewById(android.R.id.content)).getChildAt(0);
}

private boolean activityIsOk(Activity activity)
{
    boolean s1 = !(activity == null || activity.isFinishing());

    if(s1)
    {
        View v = LayoutMaster.getActivityFirstLayout(activity);
        return v.isShown() && ViewCompat.isLaidOut(v);
    }

    return false;
}
Ali Bagheri
źródło
0

Spróbuj go użyć

LayoutInflater inflater = (LayoutInflater).getApplicationContext().getSystemService(LAYOUT_INFLATER_SERVICE);
View view = inflate.from(YourActivity.this).inflate(R.layout.yourLayout, null);
K.Nikita
źródło
Czy mógłbyś również wysłać cały kod, aby upewnić się, że wymienia właściwe rzeczy. Dziękuję Ci.
kwoxer
0

Po wielu godzinach poszukiwań i testów znalazłem następujące rozwiązanie (wdrażając różne rozwiązania SO), które w każdym razie nie zawiodło.

     Runnable runnable = new Runnable() {
            @Override
            public void run() {

          //displayPopup,progress dialog or what ever action. example

                ProgressDialogBox.setProgressBar(Constants.LOADING,youractivityName.this);
            }};

Gdzie logcat wskazuje, że dzieje się awaria .. uruchom runnable .w moim przypadku przy odbiorze transmisji.

runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if(!isFinishing()) {
                    new Handler().postAtTime(runnable,2000);
                }
            }
        });
Muahmmad Tayyib
źródło
-1

spróbuj pokazać wyskakujące okienko w ten sposób

new Handler().postDelayed(new Runnable(){

    public void run() {
       popupWindow.showAtLocation(context.getWindow().getDecorView(), Gravity.CENTER,0,0);
    }

}, 200L);
jay patoliya
źródło