Android 1.6: “Android.View.WindowManager $ BadTokenexception: Incapaz de adicionar janela - o token null não é para um aplicativo”
-
26-09-2019 - |
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.
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 BroadcastListener
nã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);
}