Android 1.6: “android.view.WindowManager $ BadTokenException: No se puede agregar ventana - nula ficha no es para una aplicación”

StackOverflow https://stackoverflow.com/questions/2634991

Pregunta

Estoy intentando abrir una ventana de diálogo, pero cada vez que intento abrirlo se lanza 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)

Estoy creando llamando showDialog con id de la pantalla. El manejador onCreateDialog registra bien y me puede dar un paso a través de él sin problema, pero me he fijado que 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 le falta a esta? Algunas preguntas han hablado de tener este problema al crear un diálogo desde el onCreate, que se debe a que la actividad no ha sido creada todavía, pero esto viene de una llamada de un objeto de menú, y la variable appContext parece que está rellena correctamente en el depurador.

¿Fue útil?

Solución

En lugar de: Context appContext = this.getApplicationContext(); se debe utilizar un puntero a la actividad que está en (probablemente this).

Me picaron demasiado esto hoy en día, la parte molesta es la getApplicationContext() es literalmente de developer.android.com: (

Otros consejos

No se puede visualizar una ventana / diálogo de la aplicación a través de un contexto que no es una actividad. Trate de pasar una referencia válida actividad

Lo mismo ocurre en lo getApplicationContext.

Los documentos en el sitio androide dice que usarlo, pero no funciona ... :-P grrrrr

Sólo hacer:

dialog = new Dialog(this); 

"este" es por lo general su actividad a partir del cual se inicia el diálogo.

documentos Android sugiere utilizar getApplicationContext ();

pero no va a funcionar en lugar de que el uso de su actividad actual al crear la instancia AlertDialog.Builder o AlertDialog o diálogo ...

Ejemplo:

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

o

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

En lugar de getApplicationContext(), sólo tiene que utilizar ActivityName.this

Yo tenía 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();
  }
}

funcionaba bien la mayoría del tiempo, pero a veces se estrelló con el mismo error. Entonces me di cuenta de que en MyActivity que tuve ...

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 pasada del código aún sostenía la versión original del objeto, y por lo tanto todavía se refería a la Activity original, que no siempre existió.

tonto estúpido error, especialmente en lo que realmente no necesitas estar sosteniendo el objeto como static en el primer lugar ...

Sólo cambia en

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

En lugar de

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

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

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

Esto requiere el permiso SYSTEM_ALERT_WINDOW :

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

Como dicen los documentos:

  

Muy pocas aplicaciones debe utilizar este permiso; estas ventanas están destinados para la interacción a nivel de sistema con el usuario.

Esta es una solución sólo se debe utilizar si se requiere un diálogo que no está adherida a una actividad.

No utilice getApplicationContext() sobre la declaración dialouge

Siempre uso this o su activity.this

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

Uso

ActivityName.this

En los cuadros de diálogo anidados este problema es muy común, funciona cuando

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

se utiliza en lugar de

mDialogBuilder = new AlertDialog.Builder(getApplicationContext);

esta alternativa.

También puede hacer esto

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

Esto funcionó para mí !!

Como se dice, se necesita una actividad como contexto para el diálogo, utiliza las "YourActivity.this" para un contexto estático o cheque aquí para saber cómo usar una dinámica en un modo seguro

Trate de restablecer el tipo de ventana a dialog

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

No se olvide de utilizar el permiso android.permission.SYSTEM_ALERT_WINDOW

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í: -
utilizar esto para conseguir contexto activity para progressdialog

 progressdialog = new ProgressDialog(Splash.this);

o progressdialog = new ProgressDialog(this);

utilizar esto para conseguir contexto de aplicación para BroadcastListener      no para progressdialog.

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

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

    private ProgressDialog tProgressDialog;

a continuación, en el 'onCreate'

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

Ahora r hecho con la parte de configuración. Ahora llamar '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);
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top