it-swarm.it

Android: "BadTokenException: impossibile aggiungere la finestra: la tua attività è in esecuzione?" a mostrare la finestra di dialogo in PreferenceActivity

Mi piacerebbe chiedere un aiuto: nella mia app, ho solo un'attività, un PreferenceActivity (non serve altro, è solo una semplice app di background-sync, quindi PrefsActivity è il Main/Launcher). Dopo le preferenze di configurazione dell'utente, controlla un checkBoxPreference, che avvia (o arresta) un servizio. All'inizio, appare una finestra di dialogo. Ma ecco il problema: se l'utente preme indietro (lascia l'attività), lo avvia di nuovo e cerca di controllare checkBoxPref., Il prefsactivity si blocca. La finestra di dialogo non viene visualizzata. Non ho idea del perché e di come risolverlo.

Questo codice è esattamente lo stesso con quella parte, ciò che mi dà il problema:

PrefsActivity.Java:

   package is.it.works;

   // imports .....

   public class PrefsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {
SharedPreferences prefs;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.prefs);
    prefs = PreferenceManager.getDefaultSharedPreferences(this);
    prefs.registerOnSharedPreferenceChangeListener(this);
}// onCreate

@Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
    if (key.equals("checkTest")) {
        showDialog(1);
    }
    if (key.equals("cancel")) {
        dismissDialog(1);
    }
}// onSPC

@Override
protected Dialog onCreateDialog(int id) {
    switch (id) {
    case 1: {
        ProgressDialog dialog = new ProgressDialog(this);
        dialog.setMessage("press back twice, start the app again, and click checkbox...");
        dialog.setIndeterminate(true);
        dialog.setCancelable(true);
        dialog.setOnCancelListener(new OnCancelListener() {

            @Override
            public void onCancel(DialogInterface dialog) {
                prefs.edit().putBoolean("cancel", false).commit();
            }
        });
        return dialog;
    }// case
    }// switch
    return null;
}// onCreateDialog
}// PrefsActivity

prefs.xml:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:Android="http://schemas.Android.com/apk/res/Android">

    <CheckBoxPreference Android:key="checkTest" Android:title="test" />

</PreferenceScreen>

e il manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
package="is.it.works" Android:versionCode="1" Android:versionName="1.0">
<uses-sdk Android:minSdkVersion="4" />

<application Android:icon="@drawable/icon" Android:label="@string/app_name">
    <activity Android:name=".PrefsActivity" Android:label="@string/app_name">
        <intent-filter>
            <action Android:name="Android.intent.action.MAIN" />
            <category Android:name="Android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

</application>
</manifest>

Errore LogCat:

09-14 10:34:34.472: ERROR/AndroidRuntime(281): Uncaught handler: thread main exiting due to uncaught exception
09-14 10:34:34.502: ERROR/AndroidRuntime(281): Android.view.WindowManager$BadTokenException: Unable to add window -- token [email protected] is not valid; is your activity running?
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at Android.view.ViewRoot.setView(ViewRoot.Java:456)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at Android.view.WindowManagerImpl.addView(WindowManagerImpl.Java:177)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at Android.view.WindowManagerImpl.addView(WindowManagerImpl.Java:91)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at Android.view.Window$LocalWindowManager.addView(Window.Java:409)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at Android.app.Dialog.show(Dialog.Java:238)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at Android.app.Activity.showDialog(Activity.Java:2413)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at is.it.works.PrefsActivity.onSharedPreferenceChanged(PrefsActivity.Java:27)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at Android.app.ApplicationContext$SharedPreferencesImpl$EditorImpl.commit(ApplicationContext.Java:2727)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at Android.preference.Preference.tryCommit(Preference.Java:1199)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at Android.preference.Preference.persistBoolean(Preference.Java:1404)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at Android.preference.CheckBoxPreference.setChecked(CheckBoxPreference.Java:155)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at Android.preference.CheckBoxPreference.onClick(CheckBoxPreference.Java:143)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at Android.preference.Preference.performClick(Preference.Java:811)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at Android.preference.PreferenceScreen.onItemClick(PreferenceScreen.Java:190)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at Android.widget.AdapterView.performItemClick(AdapterView.Java:284)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at Android.widget.ListView.performItemClick(ListView.Java:3246)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at Android.widget.AbsListView$PerformClick.run(AbsListView.Java:1635)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at Android.os.Handler.handleCallback(Handler.Java:587)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at Android.os.Handler.dispatchMessage(Handler.Java:92)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at Android.os.Looper.loop(Looper.Java:123)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at Android.app.ActivityThread.main(ActivityThread.Java:4203)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at Java.lang.reflect.Method.invokeNative(Native Method)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at Java.lang.reflect.Method.invoke(Method.Java:521)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:791)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:549)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at dalvik.system.NativeStart.main(Native Method)
09-14 10:34:34.522: INFO/Process(52): Sending signal. PID: 281 SIG: 3
09-14 10:34:34.532: INFO/dalvikvm(281): threadid=7: reacting to signal 3
09-14 10:34:34.592: INFO/dalvikvm(281): Wrote stack trace to '/data/anr/traces.txt'
09-14 10:34:38.533: DEBUG/dalvikvm(107): GC freed 437 objects / 21560 bytes in 136ms
09-14 10:34:39.183: INFO/global(175): Default buffer size used in BufferedReader constructor. It would be better to be explicit if an 8k-char buffer is required.
09-14 10:34:44.632: INFO/global(175): Default buffer size used in BufferedReader constructor. It would be better to be explicit if an 8k-char buffer is required.
09-14 10:34:47.412: INFO/Process(281): Sending signal. PID: 281 SIG: 9
09-14 10:34:47.472: INFO/ActivityManager(52): Process is.it.works (pid 281) has died.
09-14 10:34:47.492: INFO/WindowManager(52): WIN DEATH: Window{4394f638 is.it.works/is.it.works.PrefsActivity paused=false} 

Dopo googleing molto, penso, la parte sbagliata è il ProgressDialog dialog = new ProgressDialog(this);. Causa this modifiche. Ma cambiarlo in getApplicationContext(), o PrefsActivity.this non aiuta, il problema è ancora lì ..__ Per favore, dimmi perché sta succedendo questo, e quale potrebbe essere la soluzione! Grazie! Sono bloccato, e ora non ho idea ...

54
Lama

Ho avuto un problema molto simile (che mi ha colpito qui) e ho trovato una soluzione molto semplice per questo. Mentre il mio codice è diverso, dovrebbe essere facile da adattare. Ecco la mia correzione:

public void showBox() {
    mActive = true;
    if (! ((Activity) mContext).isFinishing()) {
        mDialogBox.show();
    }
} 

Quindi, nel codice di esempio nella domanda, la correzione sarebbe stata (a supposizione):

@Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
    if (key.equals("checkTest")) {
        if (! this.isFinishing()) {
            showDialog(1);
        }
    }
    if (key.equals("cancel")) {
        dismissDialog(1);
    }
}// onSPC
80
Tigger

Forse non hai chiuso o non hai registrato qualcosa nella tua attività. In tal caso, prova a annullare la registrazione di broadcastreceiver su onDestroy. 

3
yoryo

Per me questo ha risolto il problema .. controllando se la finestra di dialogo è nullo o non mostra e se sì quindi creare di nuovo.

    // create alert dialog
    if (enableNetworkDialog == null || !enableNetworkDialog.isShowing())
        enableNetworkDialog = alertDialogBuilder.create();
    if (context instanceof AppCompatActivity && !((AppCompatActivity) context).isFinishing())
        enableNetworkDialog.show(); 
1
Amit Tumkur

Dopo aver introdotto il rilevamento degli arresti anomali in un progetto, ho notato che questo problema si verificava molto frequentemente e ho trovato la stessa soluzione risolta durante il progetto per eliminare l'arresto anomalo: 

  • Non dichiarare mai/istanziare le finestre di dialogo come variabili locali.
  • Crea tutte le variabili di istanza di Dialogs dell'attività.
  • Sovrascrivi onDestroy e chiama if (dialog! = Null) dialog.dismiss ();

Esempio:

MyActivity extends Activity {
  ProgressDialog mProgressDialog;
  AlertDialog mAlertDialog;


  @Override
  public void onCreate(Bundle savedInstanceState) {
    mProgressDialog = new ProgressDialog(MyActivity.this);
    mAlertDialog = new AlertDialog.Builder(MyActivity.this).show();
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    if(mProgressDialog != null) {
      mProgressDialog.dismiss();
    }
    if(mAlertDialog != null) {
      mAlertDialog.dismiss();
    }
  }

È fuorviante che il messaggio di errore indichi "impossibile aggiungere la finestra" poiché ho trovato che l'errore si verifica quando si esce da un'attività e il contesto passato alla finestra di dialogo è morto.

1

La soluzione migliore impedisce solo l'arresto anomalo. Per me il problema era che avevo indicato un context errato per mostrare la finestra di avviso. Dopo aver passato il context corretto, il problema è stato risolto.

0
TharakaNirmana

Questo di solito è causato dall'app che tenta di visualizzare una finestra di dialogo utilizzando un'attività come valore in precedenza. Quindi controlla che l'attività non sia chiusa da altre app o altri trigger prima di mostrare la finestra di dialogo

if (!isFinishing()) {
    //showdialog here
    }
0
Las Lemieux