La actividad tiene una ventana filtrada que se agregó originalmente

1163

¿Qué es este error y por qué sucede?

05-17 18:24:57.069: ERROR/WindowManager(18850): Activity com.mypkg.myP has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@44c46ff0 that was originally added here
05-17 18:24:57.069: ERROR/WindowManager(18850): android.view.WindowLeaked: Activity ccom.mypkg.myP has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@44c46ff0 that was originally added here
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.view.ViewRoot.<init>(ViewRoot.java:231)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.view.Window$LocalWindowManager.addView(Window.java:424)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.Dialog.show(Dialog.java:239)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at com.mypkg.myP$PreparePairingLinkageData.onPreExecute(viewP.java:183)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.os.AsyncTask.execute(AsyncTask.java:391)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at com.mypkg.myP.onCreate(viewP.java:94)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2544)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2621)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.ActivityThread.access$2200(ActivityThread.java:126)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1932)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.os.Handler.dispatchMessage(Handler.java:99)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.os.Looper.loop(Looper.java:123)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.ActivityThread.main(ActivityThread.java:4595)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at java.lang.reflect.Method.invokeNative(Native Method)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at java.lang.reflect.Method.invoke(Method.java:521)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at dalvik.system.NativeStart.main(Native Method)
Pentium10
fuente
66
El otro clásico es cuando cambia la orientación: stackoverflow.com/questions/1111980/…
rds

Respuestas:

1561

Intenta mostrar un cuadro de diálogo después de salir de una actividad.

[EDITAR]

Esta pregunta es una de las principales búsquedas en Google para desarrolladores de Android, por lo tanto, agrega algunos puntos importantes de los comentarios, lo que podría ser más útil para el futuro investigador sin profundizar en la conversación de comentarios.

Respuesta 1 :

Intenta mostrar un cuadro de diálogo después de salir de una actividad.

Respuesta 2

Este error puede ser un poco engañoso en algunas circunstancias (aunque la respuesta aún es completamente precisa), es decir, en mi caso, se lanzó una excepción no controlada en un AsyncTask, lo que provocó el cierre de la actividad, y luego un diálogo de progreso abierto causó esta excepción. la excepción 'real' fue un poco antes en el registro

Respuesta 3

Llame a despedir () en la instancia de Diálogo que creó antes de salir de su Actividad, por ejemplo, en onPause () o onDestroy ()

Alex Volovoy
fuente
2
@Override public void onStop () {if (dialog! = Null) {dialog.dismiss (); diálogo = nulo; }}
Md.Tarikul Islam
14
¡Incluso después de 8 años esto sigue siendo relevante! Obtuve la excepción porque la actividad se cerró mientras intentaba mostrar mi AlertDialog (respuesta 2). Al final descubrí que la aplicación estaba agregando un objeto "nulo" a la escena (no debería haber sucedido, pero sucedió) pero no dio una excepción adicional y todo fue enmascarado por el "filtrado" ventana "excepción en su lugar.
Neph
¿Es posible escanear todos los cuadros de diálogo abiertos y cerrarlos todos en onStop ()? Genero cuadros de diálogo en ListView cuando hago clic en elementos. No estoy seguro de cómo recuperar su referencia de onStop.
Myoch
1
La respuesta 3 es la mejor solución. funcionó mucho para mí Gracias Kaze, Alex!
amit bansode
consejo adicional si está mostrando el cuadro de diálogo en un bucle, asegúrese de que el bucle salga después de finalizar la actividad
Thecarisma
406

La solución es llamar dismiss()al Dialogque creó viewP.java:183antes de salir Activity, por ejemplo, en onPause(). Todos los Windows & Dialogs deben cerrarse antes de dejar un Activity.

molnarm
fuente
3
Entonces, cuando el usuario gira el teléfono, ¿todos los cuadros de diálogo deben descartarse? Eso no suena bien.
LarsH
@LarsH como pueden ver, mi respuesta fue escrita hace más de 7 años, y esto era definitivamente cierto en ese momento. Ya no trabajo con Android, pero según lo que veo en la documentación , aún podría ser el caso, pero Android ha recorrido un largo camino desde entonces (introdujo Fragments solo para nombrar uno), por lo que probablemente sea más fácil ahora.
molnarm
108

Si está utilizando AsyncTask, probablemente ese mensaje de registro puede ser engañoso. Si busca en su registro, puede encontrar otro error, probablemente uno en su doInBackground()método AsyncTask, que está haciendo que su corriente Activityexplote y, por lo tanto, una vez que AsyncTaskregrese ... bueno, ya sabe el resto. Algunos otros usuarios ya explicaron eso aquí :-)

ggomeze
fuente
22
A veces en ese caso no puedo ver la verdadera excepción. Para encontrar la verdadera excepción, simplemente comente el progressDialog.show () y ejecute la aplicación nuevamente ... ahora lo ve.
Atascado el
¡Hola amigos! Como se mencionó anteriormente por @Stuck, no puedo ver la excepción real, ¿qué hice? Localicé usando puntos de rotura y descubrí que yo estaba usando una referencia de una clase de aplicaciones dentro del método doInBackgroundde la AsyncTaskclase, pero sin declarar en el AndroidManifestarchivo usando la propiedad android:namede esta manera: android:name="my.package.MyApplicationClass". Una buena práctica al usarlo AsyncTaskes recordar siempre instanciar su alerta dentro del método onPreExecutey descartarla onPostExecute.
GFPF
66

Activé este error al llamar por error en hide()lugar de dismiss()en un AlertDialog.

Mark Phillip
fuente
44
Exactamente lo que me pasó. Además, llamar a hide () y luego configurar el diálogo como nulo tampoco es una alternativa válida.
Lucas Tulio
Realmente sabría el problema detrás de esto. Pero llamar a despedir () me ayudó!
Karoly
59

Puede obtener esta excepción simplemente por un error simple / tonto, al (por ejemplo) llamar accidentalmente finish()después de haber mostrado una AlertDialog, si pierde una declaración de interrupción de llamada en una declaración de cambio ...

   @Override
   public void onClick(View v) {
    switch (v.getId()) {
        case R.id.new_button:
            openMyAlertDialog();
            break; <-- If you forget this the finish() method below 
                       will be called while the dialog is showing!
        case R.id.exit_button:
            finish();
            break;
        }
    }

¡El finish()método cerrará el Activity, pero AlertDialogtodavía se muestra!

Entonces, cuando esté mirando fijamente el código, buscando problemas de subprocesamiento o codificación compleja y demás, no pierda de vista el bosque por los árboles. A veces puede ser algo tan simple y tonto como una declaración de ruptura faltante. :)

Adrian Romanelli
fuente
Más o menos exactamente mi problema. Se llama finalizar en onError después de crear el diálogo, no en onClick para el botón de descartar
jbass
46

Las respuestas a esta pregunta fueron correctas, pero un poco confuso para que yo realmente entienda por qué. Después de jugar durante unas 2 horas, la razón de este error (en mi caso) me golpeó:

Ya sabe, al leer otras respuestas, que el X has leaked window DecorView@d9e6131[]error tiene significa que se abrió un cuadro de diálogo cuando se cerró la aplicación. ¿Pero por qué?

Podría ser que su aplicación se bloqueó por alguna otra razón mientras su diálogo estaba abierto

Esto condujo al cierre de su aplicación debido a algún error en su código, que llevó al diálogo a permanecer abierto al mismo tiempo que su aplicación se cerró debido al otro error.

Entonces, mira a través de tu lógica. Resuelve el primer error, y luego el segundo error se resolverá soloingrese la descripción de la imagen aquí

¡Un error causa otro, que causa otro, como DOMINOS!

Ruchir Baronia
fuente
2
No puedo creer que esto solo tenga un voto a favor ... o somos realmente malos programando jajaja También me gustó tu analogía de dominó
usuario2161301
Resuelva el primer error y el segundo error no ocurrirá . Esta analogía me ayudó.
itabdullah
Esto no es del todo correcto, casos como la rotación del teléfono también pueden causar la rotación de "actividad".
Sreekanth Karumanaghat
36

Este problema surge cuando intenta mostrar un cuadro de diálogo después de salir de una actividad.

Acabo de resolver este problema simplemente escribiendo el siguiente código:

@Override
public void onDestroy(){
    super.onDestroy();
    if ( progressDialog!=null && progressDialog.isShowing() ){
        progressDialog.cancel();
    }
}

Básicamente, desde qué clase comenzaste progressDialog, reemplaza el método onDestroy y hazlo de esta manera. Se resolvió el problema "La actividad ha filtrado ventana".

Shoaib Ahmed
fuente
No se garantiza que onDestroy sea llamado. Mejor poner ese código en onPause o onStop
Amruta-Pani
19

Recientemente me enfrenté al mismo problema.

La razón detrás de este problema es que la actividad se cierra antes de cerrar el diálogo. Hay varias razones para que suceda lo anterior. Los mencionados en las publicaciones anteriores también son correctos.

Me metí en una situación, porque en el hilo, estaba llamando a una función que arrojaba una excepción. Debido a que la ventana se estaba descartando y, por lo tanto, la excepción.

Tushar
fuente
16

Descartar el diálogo cuando la actividad destruye

@Override
protected void onDestroy()
{
    super.onDestroy();
    if (pDialog!=null && pDialog.isShowing()){
        pDialog.dismiss();
    }
}
Muhammad Aamir Ali
fuente
si pDialog es nulo, esto arrojará un error al consultar el estado del diálogo nulo
Jonathan Dunn
1
no, no lo hará @JonDunn, porque Java no procesará el segundo booleano si el primero es falso
matdev
13

Esto podria ayudar.

if (! isFinishing()) {

    dialog.show();

    }
arenoso
fuente
2
Entre cientos de respuestas similares, no hay nadie que muestre cómo verificar si existen ventanas. Así que me ahorras algo de tiempo para encontrar la manera de hacerlo. Gracias.
kolyaseg
11

Tenía el mismo oscuro mensaje de error y no tenía idea de por qué. Dadas las pistas de las respuestas anteriores, cambié mis llamadas no GUI a mDialog.finish () para ser mDialog.dismiss () y los errores desaparecieron. Esto no estaba afectando el comportamiento de mi widget, pero era desconcertante y bien podría haber estado señalando una pérdida de memoria importante.

Melinda Green
fuente
Noté que estaba haciendo un mDialog.hide () antes de la llamada finish (). Cambiarlo a mDialog.dismiss () hizo el truco.
mays
11

Estaba recibiendo estos registros en mi aplicación de reproductor de video. Estos mensajes fueron lanzados mientras el reproductor de video estaba cerrado. Curiosamente, solía obtener estos registros una vez en algunas ejecuciones de manera aleatoria. Además, mi aplicación no implica ninguna progressdialog. Finalmente, solucioné este problema con la siguiente implementación.

@Override
protected void onPause()
{
    Log.v("MediaVideo", "onPause");
    super.onPause();
    this.mVideoView.pause();
    this.mVideoView.setVisibility(View.GONE);
}

@Override
protected void onDestroy()
{
    Log.v("MediaVideo", "onDestroy");
    super.onDestroy();
}

@Override
protected void onResume()
{
    Log.v("MediaVideo", "onResume");
    super.onResume();
    this.mVideoView.resume();
}

Anule la OnPausellamada a mVideoView.pause()y el conjunto visibilitya GONE. De esta manera podría resolver el " Activity has leaked window" problema de error de registro.

Punto Invisible
fuente
También estoy enfrentando el mismo problema. agregué estas líneas de código en mi código pero no funcionó y da el mismo error "android.view.WindowLeaked que se agregó originalmente" y tampoco reproduce el video y da "El video no se puede reproducir"
Usuario42590
10

Estaba teniendo el mismo problema y encontré esta página, y aunque mi situación era diferente, llamé finishdesde un ifbloque antes de definir el cuadro de alerta.

Entonces, simplemente llamar dismissno funcionaría (ya que aún no se ha hecho), pero después de leer la respuesta de Alex Volovoy y darse cuenta de que fue el cuadro de alerta lo que causó. Traté de agregar una declaración de devolución justo después del final dentro de eseif bloque y eso solucionó el problema.

Pensé que una vez que llamaste terminar, detuvo todo y terminó allí, pero no lo hace. Parece que va al final del bloque de código en el que está y luego termina.

Por lo tanto, si desea implementar una situación en la que a veces terminará antes de hacer algún código, debe colocar una declaración de devolución justo después del final o continuará y actuará como se llamó al final al final del bloque de código no donde lo llamaste. Es por eso que estaba recibiendo todos esos errores extraños.

private picked(File aDirectory){
     if(aDirectory.length()==0){
        setResult(RESULT_CANCELED, new Intent()); 
        finish(); 
        return;
    }
     AlertDialog.Builder alert= new AlertDialog.Builder(this); // Start dialog builder
     alert
        .setTitle("Question")
        .setMessage("Do you want to open that file?"+aDirectory.getName());
    alert
        .setPositiveButton("OK", okButtonListener)
        .setNegativeButton("Cancel", cancelButtonListener);
    alert.show();
}

Si no coloca la devolución justo después de que llamé terminar allí, actuará como si la hubiera llamado después del alert.show(); y, por lo tanto, diría que la ventana se filtra al terminar justo después de que aparezca el cuadro de diálogo, aunque eso sea No es el caso, todavía piensa que es.

Pensé que agregaría esto aquí, ya que esto muestra que el comando de acabado actuó de manera diferente, entonces pensé que lo hizo y supongo que hay otras personas que piensan lo mismo que yo antes de descubrir esto.

Kit Ramos
fuente
7

Esta no es la respuesta a la pregunta, pero es relevante para el tema.

Si la actividad ha definido un atributo en el Manifiesto

 android:noHistory="true"

luego, después de ejecutar onPause (), el contexto de actividad se pierde. Por lo tanto, todas las vistas que usan este contexto pueden dar este error.

Asesino
fuente
¿Puedes relacionar algo similar para progessdialog.show()... y progressdialog.hide()en asynctaskla misma actividad en lugar de onPause()desde activity? echa un vistazo a mi problema ... stackoverflow.com/questions/39332880/…
Bhuro
1
funciona perfectamente para mí: android: noHistory = "true"
Shohel Rana
6

No solo intenta mostrar una alerta, sino que también se puede invocar cuando finaliza una instancia particular de actividad e intenta iniciar una nueva actividad / servicio o intenta detenerla.

Ejemplo:

OldActivity instance;

    oncreate() {
       instance=this;
    }
    instance.finish();
    instance.startActivity(new Intent(ACTION_MAIN).setClass(instance, NewActivity.class));
Kulbhushan Chaskar
fuente
6

En general, este problema se produce debido al diálogo de progreso: puede resolverlo utilizando cualquiera de los siguientes métodos en su actividad:

 // 1):
          @Override
                protected void onPause() {
                    super.onPause();
                    if ( yourProgressDialog!=null && yourProgressDialog.isShowing() )
                  {
                        yourProgressDialog.cancel();
                    }
                }

       // 2) :
         @Override
            protected void onDestroy() {
                super.onDestroy();
                if ( yourProgressDialog!=null && yourProgressDialog.isShowing()
               {
                    yourProgressDialog.cancel();
                }
            }
Bapusaheb Shinde
fuente
5

Tuve el problema donde terminé una actividad cuando todavía se mostraba un ProgressDialog.

Entonces, primero oculte el Diálogo y luego termine la actividad.

LeonS
fuente
5

Prueba este código:

public class Sample extends Activity(){
@Override
 public void onCreate(Bundle instance){

}
 @Override
    public void onStop() {
        super.onStop();
      progressdialog.dismiss(); // try this
    }

}
tinku
fuente
progressdialog.dismiss();Esto puede crear NullPointerException.
tpk
5

Esto puede ser si tiene un error en la doInBackground()función y tiene este código.

Intenta agregar un diálogo por fin. Al principio verifica y corrige la doInBackground()función

protected void onPreExecute() {
     super.onPreExecute();
     pDialog = new ProgressDialog(CreateAccount.this);
     pDialog.setMessage("Creating Product..");
     pDialog.setIndeterminate(false);
     pDialog.setCancelable(true);
     pDialog.show();

 }

 protected String doInBackground(String...args) {
     ERROR CAN BE IS HERE
 }

 protected void onPostExecute(String file_url) {
     // dismiss the dialog once done
     pDialog.dismiss();
NickUnuchek
fuente
5

Esto me sucedió cuando estoy usando ProgressDialogen AsyncTask. En realidad estoy usando el hide()método en onPostExecute. Sobre la base de la respuesta de @Alex Volovoy necesito utilizar dismiss()con ProgressDialogpara eliminarlo en onPostExecute y su hecho.

progressDialog.hide(); // Don't use it, it gives error

progressDialog.dismiss(); // Use it
SANAT
fuente
Esta no es realmente la respuesta completa. Hay dos formas de filtrar un diálogo. 1) Si tiene un AsyncTasky muestra el Dialog, entonces sucede algo que hace la Activityllamada onPause()(tal vez algo de lógica en su AsyncTask en sí, como un oyente, entonces se filtrará. 2) Como se mencionó anteriormente, lo Dialogque se creó con eso Activity Contextnunca es despedido y los Activitymovimientos en adelante.
tricknology
5

El " Activity has leaked window that was originally added..." error se produce cuando intenta mostrar una alerta después de que el Activityes efectivafinished .

Tienes dos opciones AFAIK:

  1. Reconsidere el inicio de sesión de su alerta: llame dismiss()aldialog antes realmente salir de su actividad.
  2. Coloque el dialogen un hilo diferente y ejecútelo thread(independientemente de la corriente activity).
Kyle Clegg
fuente
5

Aquí hay una solución cuando desea cerrar AlertDialog pero no desea mantener una referencia a él dentro de la actividad.

la solución requiere que tengas androidx.lifecycle dependencia de en tu proyecto (creo que en el momento del comentario es un requisito común)

esto le permite delegar el descarte del cuadro de diálogo en un objeto externo (observador), y ya no necesita preocuparse por él, porque se cancela automáticamente cuando la actividad muere. (aquí está la prueba: https://github.com/googlecodelabs/android-lifecycles/issues/5 ).

entonces, el observador mantiene la referencia al diálogo, y la actividad mantiene la referencia al observador. cuando ocurre "onPause" - el observador cierra el diálogo, y cuando ocurre "onDestroy" - la actividad elimina al observador, por lo que no ocurre ninguna fuga (bueno, al menos ya no veo ningún error en logcat)

// observer
class DialogDismissLifecycleObserver( private var dialog: AlertDialog? ) : LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    fun onPause() {
        dialog?.dismiss()
        dialog = null
    }
}
// activity code
private fun showDialog() {
        if( isDestroyed || isFinishing ) return
        val dialog = AlertDialog
            .Builder(this, R.style.DialogTheme)
            // dialog setup skipped
            .create()
        lifecycle.addObserver( DialogDismissLifecycleObserver( dialog ) )
        dialog.show()
}
dmz9
fuente
4

Las excepciones de ventana filtrada tienen dos razones:

1) mostrando el cuadro de diálogo cuando no existe el contexto de la actividad, para resolver esto, debe mostrar el cuadro de diálogo solo si está seguro de que existe la actividad:

if(getActivity()!= null && !getActivity().isFinishing()){
        Dialog.show();
}

2) no descarte el diálogo adecuadamente, para resolver use este código:

@Override
public void onDestroy(){
    super.onDestroy();
    if ( Dialog!=null && Dialog.isShowing() ){
        Dialog.dismiss();
}
}
Jerez
fuente
4

Tienes que hacer Progressdialogobjeto en onPreExecutemétodo de AsyncTasky deberías dismisshacerlo en onPostExecutemétodo.

estoy enojado
fuente
4

La mejor solución es agregar un cuadro de diálogo en el cuadro de diálogo intentar capturar y descartar cuando se produzca una excepción

Solo usa el siguiente código

 try {
        dialog.show();
    } catch (Exception e) {
        dialog.dismiss();
    }
Ness Tyagi
fuente
3
? No está diálogo será nulo después de llamada terminado, creo que dialog.dismiss()va a producir el error demasiado
Ashu Kumar
3

En mi caso, la razón fue que olvidé incluir un permiso en el archivo de manifiesto de Android.

¿Cómo me enteré? Bueno, al igual que @Bobby dice en un comentario debajo de la respuesta aceptada, solo desplácese más arriba hasta sus registros y verá la primera razón o evento que realmente arrojó la Excepción. Aparentemente, el mensaje "La ventana de actividad se filtró que se agregó originalmente" es solo una Excepción que resultó de la primera Excepción.

Matthew Quiros
fuente
3

Pruebe el siguiente código, funcionará cada vez que cierre el diálogo de progreso y verá si su instancia está disponible o no.

try {
        if (null != progressDialog && progressDialog.isShowing()) {
            progressDialog.dismiss();
            progressDialog = null;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
Desarrollador
fuente
2

La mejor solución es poner esto antes de mostrar progressbaroprogressDialog

if (getApplicationContext().getWindow().getDecorView().isShown()) {

  //Show Your Progress Dialog

}
Ali Akram
fuente
Esto no funciona para mi. Tengo Dialog.show () después de la respuesta de la llamada HTTP y, mientras tanto, giro la pantalla La actividad se desconecta pero parece que isShown == true antes de Dialog.show () y luego el diálogo se bloquea a pesar de esta comprobación
Michał Ziobro
1

Solo asegúrese de que su actividad no se cierre inesperadamente debido a algunas excepciones generadas en algún lugar de su código. Generalmente ocurre en una tarea asincrónica cuando la actividad enfrenta un cierre forzado en el método doinBackground y luego asynctask regresa al método onPostexecute.

Manas Ranjan
fuente
1

Tengo otra solución para esto, y me gustaría saber si le parece válido: en lugar de descartar en onDestroy, que parece ser la solución principal, estoy extendiendo ProgressDialog ...

public class MyProgressDialog extends ProgressDialog {

  private boolean isDismissed;

  public MyProgressDialog(Context context) {
    super(context);
  }

  @Override
  public void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    dismiss();
  }

  @Override
  public void dismiss() {
    if (isDismissed) {
      return;
    }
    try {
      super.dismiss();
    } catch (IllegalArgumentException e) {
      // ignore
    }
    isDismissed = true;
  }

Esto es preferible, AFAIC, porque no tienes que mantener el diálogo de progreso como miembro, solo dispara (muestra) y olvida

Kalisky
fuente