2011-09-14 16 views
51

Vorrei chiedere aiuto: Nella mia app, ho solo una attività, una PreferenceActivity (non serve altro, è solo una semplice app di sincronizzazione in background, quindi il PrefsActivity è il principale/Launcher). Dopo le preferenze di configurazione dell'utente, controlla un checkBoxPreference e questo avvia (o arresta) un servizio. All'inizio, appare una finestra di dialogo. Ma questo è il problema: se l'utente torna indietro (lascia l'attività), riavvialo e tenta di controllare lo checkBoxPref., Gli arresti prefsactivity. La finestra di dialogo non viene visualizzata. Non ho idea del perché e di come risolverlo.Android: "BadTokenException: impossibile aggiungere la finestra: la tua attività è in esecuzione?" a mostrare la finestra di dialogo in PreferenceActivity

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 manifesto:

<?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, credo, la parte sbagliata è la ProgressDialog dialog = new ProgressDialog(this);. Causa modifiche this. 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 ne ho idea ...

+4

uso getParent() al posto di questo e cercare – Abhi

+1

useing getParent(), mi dà NullPointerException. :( – Lama

+4

controllare questo link [BadTokenException] (http://vinnysoft.blogspot.com/2010/11/androidviewwindowmanagerbadtokenexcepti.html). Questo vi aiuterà. Grazie Venky. – Venky

risposta

3

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

77

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

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

Così, nel codice di esempio nella questione, la correzione sarebbe stato (a occhio e croce):

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

Devi non confrontare un booleano con un altro booleano, ma usare invece l'operatore booleano '!' (o niente). – Darkhogg

+0

In base al [documento Android] (http://developer.android.com/reference/android/app/Activity.html#isFinishing()) - 'isFinishing()' restituisce 'true' o' false'. Dopo un po 'di ricerche su quando è corretto usare 'if (! Boolean)' o 'if (booleano == false)', non sono riuscito a trovare nulla di definito. Hai un link o qualcosa che posso verificare per eseguire il backup della tua dichiarazione? – Tigger

+7

È una questione di stile, non di funzionalità. Entrambi sono tecnicamente uguali, ma: http://stackoverflow.com/questions/2661110/is-it-bad-to-explicitly-compare-against-boolean-constants-eg-if-b-false-i http : //programmers.stackexchange.com/questions/136908/why-use-boolean-variable-over-boolean-variable-false Quest'ultimo ha una risposta che mi piace: è più facile da leggere, come in '!' si legge come * not * e gli identificatori Java di solito sono leggibili in inglese. – Darkhogg

1

Dopo aver introdotto il monitoraggio incidente a un progetto, ho notato questo problema popping up abbastanza frequentemente e trovato la stessa soluzione ha lavorato tutto il progetto di eliminare l'incidente:

  • Mai dichiarano/istanziare finestre di dialogo come variabili locali.
  • Imposta tutte le variabili di istanza delle finestre di dialogo dell'attività.
  • Ignora 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(); 
    } 
    } 

E 'fuorviante che il messaggio di errore dice "incapace di aggiungere finestra" come ho trovato l'errore si verifica quando si sta lasciando un'attività e il contesto che è stato passato a il tuo Dialogo è morto.

+0

sei sicuro di aver bisogno di chiudere da solo le finestre di dialogo? il codice di Android per l'attività sembra già li chiude per voi: http://grepcode.com/file_/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/app /Activity.java/?v=source –

+0

Sì, sembra corretto. Di solito lavoro su basi di codici composte da frammenti, quindi suppongo che intendessi questo post per i frammenti quando l'ho scritto in agosto. Lo esaminerò e aggiornerò il post. –

+4

che cosa è corretto? cosa ho scritto o cosa hai scritto? –

0

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

+0

Il contesto corretto è cosa? Contesto applicativo? –

0

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