Android 1.6: "android.view.WindowManager $ BadTokenException: no se puede agregar la ventana; el token nulo no es para una aplicación"


303

Estoy tratando de abrir una ventana de diálogo, pero cada vez que intento abrirla arroja esta excepción:

Uncaught handler: thread main exiting due to uncaught exception
android.view.WindowManager$BadTokenException: 
     Unable to add window -- token null is not for an application
  at android.view.ViewRoot.setView(ViewRoot.java:460)
  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
  at android.app.Dialog.show(Dialog.java:238)
  at android.app.Activity.showDialog(Activity.java:2413)

Lo estoy creando llamando showDialogcon la identificación de la pantalla. El onCreateDialogcontrolador se registra bien y puedo recorrerlo sin problemas, pero lo adjunto ya que parece que me falta algo:

@Override
public Dialog onCreateDialog(int id)
{
    Dialog dialog;
    Context appContext = this.getApplicationContext();
    switch(id)
    {
        case RENAME_DIALOG_ID:
            Log.i("Edit", "Creating rename dialog...");
            dialog = new Dialog(appContext);
            dialog.setContentView(R.layout.rename);
            dialog.setTitle("Rename " + noteName);
            break;
        default:
            dialog = null;
            break;
    }
    return dialog;      
}

¿Hay algo que falta en esto? Algunas preguntas han hablado acerca de tener este problema al crear un cuadro de diálogo onCreate, lo que ocurre porque la actividad aún no se ha creado, pero esto proviene de una llamada de un objeto de menú y appContextparece que la variable se rellena correctamente en el depurador.

Respuestas:


609

En lugar de: Context appContext = this.getApplicationContext(); debería usar un puntero a la actividad en la que se encuentra (probablemente this).

Esto también me mordió hoy, la parte molesta getApplicationContext()es literalmente de developer.android.com :(


2
También se informa como un error (aunque no fue cuando el usuario publicó la pregunta): code.google.com/p/android/issues/detail?id=11199
Raymond Martineau

63
En caso de que esto ayude a alguien, use myActivity. Este es su contexto en un diálogo.
Rab Ross

13
Esta pregunta y respuesta cumple 3 años en 2 días. Todavía estoy ganando reputación, así que supongo que Google todavía no ha arreglado sus documentos ...
Torp


66
Esto es abril de 2016, y aún esta excepción hace que la aplicación se bloquee al iniciar el diálogo.
Yogesh Seralia

78

No puede mostrar una ventana / diálogo de aplicación a través de un Contexto que no es una Actividad. Intenta pasar una referencia de actividad válida


¿cómo? Lo intenté activity.thisy activity.getBaseContext()no sirvió de nada. ¿Alguna ayuda?
Darpan

3
Entendido. Pase directamente el nombre de su actividad en él. Sin .this.
Darpan

45

Lo mismo ocurre con el tema getApplicationContext.

Los documentos en el sitio de Android dicen que lo use, pero no funciona ... grrrrr :-P

Solo haz:

dialog = new Dialog(this); 

"esto" suele ser su actividad desde la que inicia el diálogo.


43

Los documentos de Android sugieren usar getApplicationContext ();

pero no funcionará en lugar de usar su actividad actual al crear instancias de AlertDialog.Builder o AlertDialog o Dialog ...

Ex:

AlertDialog.Builder builder = new  AlertDialog.Builder(this);

o

AlertDialog.Builder builder = new  AlertDialog.Builder((Your Activity).this);

Esto me ayudó masivamente. Estaba tratando de crear un diálogo desde otro diálogo y solo tenía "AlertDialog.Builder (this);" Estaba dando un error. ¡Gracias!
EHarpham

(ActivityName.this) es especialmente útil al intentar crear un cuadro de diálogo dentro de
onHaga

Mi problema es que estoy creando un ProgressDialog dentro de un AlertDialog dentro de un adaptador ... No puedo hacer que funcione.
Martin Erlic


13

Tuve un problema similar donde tuve otra clase algo como esto:

public class Something {
  MyActivity myActivity;

  public Something(MyActivity myActivity) {
    this.myActivity=myActivity;
  }

  public void someMethod() {
   .
   .
   AlertDialog.Builder builder = new AlertDialog.Builder(myActivity);
   .
   AlertDialog alert = builder.create();
   alert.show();
  }
}

Funcionó bien la mayor parte del tiempo, pero a veces fallaba con el mismo error. Entonces me doy cuenta de que MyActivitytenía ...

public class MyActivity extends Activity {
  public static Something something;

  public void someMethod() {
    if (something==null) {
      something=new Something(this);
    }
  }
}

Debido a que estaba sosteniendo el objeto como static, una segunda ejecución del código todavía contenía la versión original del objeto y, por lo tanto, todavía se refería al original Activity, que ya no existía.

Error tonto y estúpido, especialmente porque realmente no necesitaba estar sosteniendo el objeto como staticen primer lugar ...


12

Solo cámbielo a

AlertDialog.Builder alert_Categoryitem = 
    new AlertDialog.Builder(YourActivity.this);

En vez de

AlertDialog.Builder alert_Categoryitem = 
    new AlertDialog.Builder(getApplicationContext());

9

Otra solución es establecer el tipo de ventana en un cuadro de diálogo del sistema:

dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

Esto requiere el SYSTEM_ALERT_WINDOWpermiso:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

Como dicen los documentos:

Muy pocas aplicaciones deberían usar este permiso; Estas ventanas están destinadas a la interacción a nivel de sistema con el usuario.

Esta es una solución que solo debe usar si necesita un cuadro de diálogo que no esté asociado a una actividad.


Este indicador ahora está en desuso desde el nivel 26 de API. Porque permite al desarrollador jugar con la ventana del sistema, lo que no es bueno desde la perspectiva del usuario.
CopsOnRoad

4

No lo use getApplicationContext()para declarar dialouge

Siempre use thiso suactivity.this


2

Para los diálogos anidados, este problema es muy común, funciona cuando

AlertDialog.Builder mDialogBuilder = new AlertDialog.Builder(MyActivity.this);

se usa en lugar de

mDialogBuilder = new AlertDialog.Builder(getApplicationContext);

Esta alternativa.


2

Esto funcionó para mí

new AlertDialog.Builder(MainActivity.this)
        .setMessage(Html.fromHtml("<b><i><u>Spread Knowledge Unto The Last</u></i></b>"))
        .setCancelable(false)
        .setPositiveButton("Dismiss",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                    }
                }).show();

Utilizar

ActivityName.this

0

También puedes hacer esto

public class Example extends Activity {
    final Context context = this;
    final Dialog dialog = new Dialog(context);
}

¡Esto funcionó para mí!


0

Como se dice, necesita una Actividad como contexto para el diálogo, use "YourActivity.this" para un contexto estático o verifique aquí cómo usar uno dinámico en un modo seguro


0

Intenta restablecer dialogel tipo de ventana a

WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

No olvides usar el permiso android.permission.SYSTEM_ALERT_WINDOW


0
public class Splash extends Activity {

    Location location;
    LocationManager locationManager;
    LocationListener locationlistener;
    ImageView image_view;
    ublic static ProgressDialog progressdialog;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.splash);
        progressdialog = new ProgressDialog(Splash.this);
           image_view.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub

                        locationManager.requestLocationUpdates("gps", 100000, 1, locationlistener);
                        Toast.makeText(getApplicationContext(), "Getting Location plz wait...", Toast.LENGTH_SHORT).show();

                            progressdialog.setMessage("getting Location");
                            progressdialog.show();
                            Intent intent = new Intent(Splash.this,Show_LatLng.class);
//                          }
        });
    }

Texto aquí:
use esto para obtener activitycontexto paraprogressdialog

 progressdialog = new ProgressDialog(Splash.this);

o progressdialog = new ProgressDialog(this);

use esto para obtener el contexto de la aplicación para BroadcastListener no para progressdialog.

progressdialog = new ProgressDialog(getApplicationContext());
progressdialog = new ProgressDialog(getBaseContext());

0

La mejor y más segura forma de mostrar un 'ProgressDialog' en una AsyncTask, evitando problemas de pérdida de memoria es usar un 'Handler' con Looper.main ().

    private ProgressDialog tProgressDialog;

luego en 'onCreate'

    tProgressDialog = new ProgressDialog(this);
    tProgressDialog.setMessage(getString(R.string.loading));
    tProgressDialog.setIndeterminate(true);

Ahora ha terminado con la parte de configuración. Ahora llame a 'showProgress ()' y 'hideProgress ()' en AsyncTask.

    private void showProgress(){
        new Handler(Looper.getMainLooper()){
            @Override
            public void handleMessage(Message msg) {
                tProgressDialog.show();
            }
        }.sendEmptyMessage(1);
    }

    private void hideProgress(){
        new Handler(Looper.getMainLooper()){
            @Override
            public void handleMessage(Message msg) {
                tProgressDialog.dismiss();
            }
        }.sendEmptyMessage(1);
    }
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.