Android 1.6: “android.view.WindowManager $ BadTokenException: não foi possível adicionar a janela - o token nulo não é para um aplicativo”


303

Estou tentando abrir uma janela de diálogo, mas toda vez que tento abri-la, gera essa exceção:

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)

Estou criando chamando showDialogcom o ID do display. O onCreateDialogmanipulador registra bem e eu posso percorrê-lo sem problemas, mas o anexei, pois parece que estou perdendo alguma coisa:

@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;      
}

Há algo faltando nisso? Algumas perguntas falaram sobre ter esse problema ao criar uma caixa de diálogo onCreate, o que acontece porque a atividade ainda não foi criada, mas isso é proveniente de uma chamada de um objeto de menu e a appContextvariável parece estar corretamente preenchida no depurador.

Respostas:


609

Em vez de: Context appContext = this.getApplicationContext(); você deve usar um ponteiro para a atividade em que está (provavelmente this).

Fui mordido por isso hoje também, a parte irritante é a getApplicationContext()é literalmente do developer.android.com :(


2
Ele também é relatado como um bug (embora não tenha sido quando o usuário postou a pergunta): code.google.com/p/android/issues/detail?id=11199
Raymond Martineau

63
Caso isso ajude alguém - use myActivity.this como seu contexto em uma caixa de diálogo.
Rab Ross 5/12

13
Esta pergunta e resposta faz 3 anos em 2 dias. Eu ainda estou recebendo reputação, então eu acho que o Google ainda não fixaram seus docs ...
Torp


6
Isso é abril de 2016, e ainda essa exceção causa falha no aplicativo no início da caixa de diálogo.
Yogesh Seralia

78

Você não pode exibir uma janela / caixa de diálogo do aplicativo por meio de um contexto que não é uma atividade. Tente passar uma referência de atividade válida


como? Eu tentei activity.thise activity.getBaseContext()sem sucesso. Qualquer ajuda?
Darpan 15/10

3
Entendi. Passe diretamente o nome da sua atividade. Sem .this.
Darpan 15/10

45

O mesmo acontece na coisa getApplicationContext.

Os documentos no site android dizem para usá-lo, mas não funciona ... grrrrr :-P

Apenas faça:

dialog = new Dialog(this); 

"this" é geralmente sua atividade a partir da qual você inicia a caixa de diálogo.


43

Os documentos do Android sugerem o uso de getApplicationContext ();

mas não funcionará, em vez de usar sua atividade atual ao instanciar AlertDialog.Builder ou AlertDialog ou Dialog ...

Ex:

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

ou

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

Isso me ajudou muito. Eu estava tentando criar uma caixa de diálogo dentro de outra caixa e apenas com "AlertDialog.Builder (this);" estava dando um erro. Obrigado!
EHarpham 20/10/12

(ActivityName.this) é especialmente útil ao tentar criar uma caixa de diálogo dentro de um
clique de

Meu problema é que estou criando um ProgressDialog dentro de um AlertDialog dentro de um adaptador ... Não consigo fazê-lo funcionar.
Martin Erlic 06/07/19


13

Eu tive um problema semelhante em que tive outra classe, algo como isto:

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

Funcionava bem na maioria das vezes, mas às vezes falhava com o mesmo erro. Então eu percebo que MyActivityeu tinha ...

public class MyActivity extends Activity {
  public static Something something;

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

Como eu estava segurando o objeto como static, uma segunda execução do código ainda mantinha a versão original do objeto e, portanto, ainda estava se referindo ao original.Activity , que não existia mais.

Erro estúpido bobo, especialmente porque eu realmente não precisava segurar o objeto como staticem primeiro lugar ...


12

Apenas mude para

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

Ao invés de

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

9

Outra solução é definir o tipo de janela para uma caixa de diálogo do sistema:

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

Isso requer a SYSTEM_ALERT_WINDOWpermissão:

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

Como dizem os documentos:

Muito poucos aplicativos devem usar essa permissão; essas janelas destinam-se à interação no nível do sistema com o usuário.

Esta é uma solução que você deve usar apenas se precisar de uma caixa de diálogo que não esteja anexada a uma atividade.


Agora, esse sinalizador foi descontinuado do nível 26 da API. Porque permite que o desenvolvedor jogue com a janela do sistema, o que não é bom da perspectiva do usuário.
CopsOnRoad

4

Não use getApplicationContext()na declaração de discagem

Sempre use thisou seuactivity.this


2

Para diálogos aninhados, esse problema é muito comum, funciona quando

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

é usado em vez de

mDialogBuilder = new AlertDialog.Builder(getApplicationContext);

essa alternativa.


2

Isso funcionou para mim--

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

Usar

ActivityName.this

0

Você também pode fazer isso

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

Isso funcionou para mim !!


0

Como foi dito, você precisa de uma Atividade como contexto para a caixa de diálogo, use "YourActivity.this" para um contexto estático ou verifique aqui como usar uma dinâmica em um modo de segurança


0

Tente redefinir dialogo tipo da janela para

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

Não se esqueça de usar a permissão 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 aqui: -
use isso para obter activitycontexto paraprogressdialog

 progressdialog = new ProgressDialog(Splash.this);

ou progressdialog = new ProgressDialog(this);

use isso para obter o contexto do aplicativo para BroadcastListener não progressdialog.

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

0

A melhor e a maneira mais segura de mostrar um 'ProgressDialog' em um AsyncTask, evitando problemas de vazamento de memória, é usar um 'Handler' com Looper.main ().

    private ProgressDialog tProgressDialog;

depois no 'onCreate'

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

Agora você terminou a parte de configuração. Agora chame 'showProgress ()' e 'hideProgress ()' no 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);
    }
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.