Android 1.6: “Android.View.WindowManager $ BadTokenexception: Incapaz de adicionar janela - o token null não é para um aplicativo”

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

Pergunta

Estou tentando abrir uma janela de diálogo, mas toda vez que tento abri -la, ele lança esta 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 ligando showDialog com o ID da tela. o onCreateDialog O manipulador registra bem e eu posso passar por isso sem um problema, mas eu 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 disso? Algumas perguntas falaram sobre ter esse problema ao criar um diálogo de onCreate, o que acontece porque a atividade ainda não foi criada, mas isso vem de uma chamada de um objeto de menu, e o appContext A variável parece que está corretamente preenchida no depurador.

Foi útil?

Solução

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

Eu fui mordido por isso hoje também, a parte irritante é o getApplicationContext() é literal de desenvolvedor.android.com :(

Outras dicas

Você não pode exibir uma janela/diálogo de aplicativos através de um contexto que não é uma atividade. Tente passar uma referência de atividade válida

O mesmo vale na coisa do getApplicationContext.

Os documentos no site do Android dizem para usá-lo, mas não funciona ... grrrrr :-p

Apenas faça:

dialog = new Dialog(this); 

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

Documentos Android sugere usar getApplicationContext ();

Mas não funcionará em vez disso, use sua atividade atual enquanto instanciava o alertdialog.builder ou alertdialog ou diálogo ...

Ex:

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

ou

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

Ao invés de getApplicationContext(), Apenas use ActivityName.this

Eu tive um problema semelhante em que tive outra aula algo assim:

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

Funcionou bem na maioria das vezes, mas às vezes caiu com o mesmo erro. Então eu percebo que em MyActivity Eu tive...

public class MyActivity extends Activity {
  public static Something something;

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

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

Erro estúpido bobo, especialmente porque eu realmente não precisava estar segurando o objeto como static em primeiro lugar...

Apenas mude para

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

Ao invés de

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

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 o SYSTEM_ALERT_WINDOW permissão:

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

Como os documentos dizem:

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 seja anexada a uma atividade.

Não use getApplicationContext() ao declarar dialouge

Sempre use this ou seu activity.this

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

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

esta alternativa.

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

Como se diz, você precisa de uma atividade como contexto para a caixa de diálogo, use "yourActivity.This" para um contexto estático ou verifique aqui para como usar um dinâmico em um modo de segurança

Tente redefinir dialog tipo de 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

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 conseguir activity contexto para progressdialog

 progressdialog = new ProgressDialog(Splash.this);

ou progressdialog = new ProgressDialog(this);

Use isso para obter o contexto do aplicativo para BroadcastListenernão para progressdialog.

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

A melhor e mais segura maneira de mostrar um 'ProgressDialog' em uma asynctask, evitar o problema de vazamento de memória é usar um 'manipulador' com looper.main ().

    private ProgressDialog tProgressDialog;

Então no 'onCreate'

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

Agora você está pronto com a parte de configuração. Agora ligue para 'SlightRess ()' e 'hideProgress ()' no assíncastão.

    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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top