2011-09-14 7 views
51

Me gustaría pedir ayuda: en mi aplicación, tengo una sola actividad, PreferenceActivity (no necesito otra, es simplemente una aplicación de sincronización de fondo, por lo que PrefsActivity es la Main/Launcher). Después de las preferencias de configuración del usuario, comprueba un checkBoxPreference y eso inicia (o detiene) un servicio. Al comenzar, aparece un diálogo. Pero aquí está el problema: si el usuario presiona hacia atrás (abandona la actividad), inícielo de nuevo y luego trata de marcar checkBoxPref., prefsactivity se bloquea. Dialog no se muestra. No tengo idea de por qué y cómo solucionarlo.Android: "BadTokenException: no se puede agregar la ventana; ¿se está ejecutando su actividad?" al mostrar el cuadro de diálogo en PreferenceActivity

Este código es exactamente igual con esa parte, lo que me da el 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> 

y el manifiesto:

<?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> 

error 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} 

Después googleing mucho, creo, la parte equivocada es la ProgressDialog dialog = new ProgressDialog(this);. Causa this cambios. Pero cambiarlo a getApplicationContext(), o PrefsActivity.this no ayuda, el problema sigue ahí. Por favor, dime por qué sucede esto y cuál podría ser la solución. ¡Gracias! Estoy atascado, y ahora no tengo idea ...

+4

uso getParent() en lugar de esto y tratar – Abhi

+1

useing getParent(), me da NullPointerException. :( – Lama

+4

Revise este enlace [BadTokenException] (http://vinnysoft.blogspot.com/2010/11/androidviewwindowmanagerbadtokenexcepti.html). Esto lo ayudará. Gracias, Venky. – Venky

Respuesta

3

Tal vez no cerró o anuló el registro de algo en su actividad. En ese caso, intente eliminar el registro del receptor de difusión en onDestroy.

77

Tuve un problema muy similar (que me aterrizó aquí) y encontré una solución muy simple para él. Si bien mi código es diferente, debería ser fácil de adaptar. Aquí está mi solución:

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

Por lo tanto, en el código de ejemplo en la cuestión, la solución habría sido (a ojo):

@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

Debería no comparar un booleano con otro booleano, sino usar el operador booleano '!' (o nada) en su lugar. – Darkhogg

+0

Según los [documentos de Android] (http://developer.android.com/reference/android/app/Activity.html#isFinishing()) - 'isFinishing()' devuelve 'true' o' false'. Después de un poco de investigación sobre cuándo es correcto usar 'if (! Boolean)' o 'if (boolean == false)', no pude encontrar nada definitivo. ¿Tiene un enlace o algo que pueda verificar para respaldar su estado de cuenta? – Tigger

+7

Es una cuestión de estilo, no de funcionalidad. Ambas son técnicamente iguales, pero: http://stackoverflow.com/questions/2661110/is-it-bad-to-explícitamente-compara-una-confianza-bolera-eg-if-b-false-i http : //programmers.stackexchange.com/questions/136908/why-use-boolean-variable-over-boolean-variable-false Este último tiene una respuesta que me gusta: es más fácil de leer, como en '!' lee como * no * y los identificadores de Java generalmente son legibles en inglés. – Darkhogg

1

Después de introducir el seguimiento de choque para un proyecto, me di este problema apareció con bastante frecuencia y encontró el mismo arreglo trabajado en todo el proyecto para eliminar el bloqueo:

  • Nunca declarar/instanciar cuadros de diálogo como variables locales.
  • Realiza todas las variables de instancia de Dialogs de la Actividad.
  • Anular onDestroy y llamar a if (dialog! = Null) dialog.dismiss();

Ejemplo:

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

Es un error que dice el mensaje de error "no puede agregar ventana" como yo he encontrado el error ocurre cuando se está saliendo de una actividad y el contexto que se ha pasado tu Diálogo está muerto.

+0

¿está seguro de que tiene que cerrar los diálogos usted mismo? el código de Android para la actividad parece que ya los ha cerrado: 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í, parece ser correcto. Normalmente trabajo en bases de código compuestas de fragmentos, así que supongo que quise decir esta publicación para fragmentos cuando la escribí en agosto. Lo investigaré y actualizaré la publicación. –

+4

¿qué es correcto? ¿Qué he escrito o qué has escrito? –

0

La solución superior solo evita el bloqueo.Para mí, el problema era que había enviado un mensaje de error context para mostrar el cuadro de diálogo de alerta. Después de pasar el context correcto, se solucionó el problema.

+0

¿Cuál es el contexto correcto? Contexto de la aplicación? –

0

Para mí esto resolvió el problema ... verificando si el diálogo es nulo o no se muestra y si es así, vuelve a crear.

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