pagina - "Android.view.WindowManager $ BadTokenException: no se puede agregar la ventana" en buider.show()
ocultar barra de navegacion chrome (7)
De mi actividad principal, necesito llamar a una clase interna y en un método dentro de la clase, necesito mostrar AlertDialg y descartarlo cuando se presiona el botón Aceptar y reenviarlo a Google Play para comprarlo.
Las cosas funcionan perfectamente la mayoría de las veces, pero para algunos usuarios se bloquea en builder.show()
y puedo ver "android.view.WindowManager$BadTokenException:
no se puede agregar la ventana" del registro de bloqueo. Por favor recomiende.
Mi código es bastante parecido a esto:
public class classname1 extends Activity{
public void onCreate(Bundle savedInstanceState) {
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.<view>);
//call the <className1> class to execute
}
private class classNamename2 extends AsyncTask<String, Void, String>{
protected String doInBackground(String... params) {}
protected void onPostExecute(String result){
if(page.contains("error"))
{
AlertDialog.Builder builder = new AlertDialog.Builder(classname1.this);
builder.setCancelable(true);
builder.setMessage("");
builder.setInverseBackgroundForced(true);
builder.setNeutralButton("Ok",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton){
dialog.dismiss();
if(!<condition>)
{
try
{
String pl = "";
mHelper.<flow>(<class>.this, SKU, RC_REQUEST,
<listener>, pl);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
});
builder.show();
}
}
}
}
También he visto el error en otra alerta en la que no estoy reenviando a ninguna otra actividad. Es simple como esto:
AlertDialog.Builder builder = new AlertDialog.Builder(classname1.this);
builder.setCancelable(true);
//if successful
builder.setMessage(" ");
builder.setInverseBackgroundForced(true);
builder.setNeutralButton("Ok",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton){
// dialog.dismiss();
}
});
builder.show();
}
Estoy creando Dialog en onCreate
y usándolo con show
y hide
. Para mí, la causa raíz no descartaba onBackPressed
, que estaba terminando la actividad de Home
.
@Override
public void onBackPressed() {
new AlertDialog.Builder(this)
.setTitle("Really Exit?")
.setMessage("Are you sure you want to exit?")
.setNegativeButton(android.R.string.no, null)
.setPositiveButton(android.R.string.yes,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
Home.this.finish();
return;
}
}).create().show();
Estaba terminando la Actividad en el hogar onBackPressed
sin cerrar / descartar mis diálogos.
Cuando descarté mis diálogos, el accidente desapareció.
new AlertDialog.Builder(this)
.setTitle("Really Exit?")
.setMessage("Are you sure you want to exit?")
.setNegativeButton(android.R.string.no, null)
.setPositiveButton(android.R.string.yes,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
networkErrorDialog.dismiss() ;
homeLocationErrorDialog.dismiss() ;
currentLocationErrorDialog.dismiss() ;
Home.this.finish();
return;
}
}).create().show();
La posible razón es el contexto del diálogo de alerta. Puede finalizar esa actividad, por lo que intenta abrir en ese contexto, pero que ya está cerrado. Intente cambiar el contexto de ese diálogo para su primera actividad porque no estará terminado hasta el final.
p.ej
En vez de esto.
AlertDialog alertDialog = new AlertDialog.Builder(this).create();
tratar de usar
AlertDialog alertDialog = new AlertDialog.Builder(FirstActivity.getInstance()).create();
Prueba esto :
public class <class> extends Activity{
private AlertDialog.Builder builder;
public void onCreate(Bundle savedInstanceState) {
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.<view>);
builder = new AlertDialog.Builder(<class>.this);
builder.setCancelable(true);
builder.setMessage(<message>);
builder.setInverseBackgroundForced(true);
//call the <className> class to execute
}
private class <className> extends AsyncTask<String, Void, String>{
protected String doInBackground(String... params) {
}
protected void onPostExecute(String result){
if(page.contains("error")) //when not subscribed
{
if(builder!=null){
builder.setNeutralButton("Ok",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton){
dialog.dismiss();
if(!<condition>)
{
try
{
String pl = "";
mHelper.<flow>(<class>.this, SKU, RC_REQUEST,
<listener>, pl);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
});
builder.show();
}
}
}
}
Tenía una función para mostrar el diálogo:
void showDialog(){
new AlertDialog.Builder(MyActivity.this)
...
.show();
}
Estaba recibiendo este error y solo tuve que verificar isFinishing()
antes de llamar a este cuadro de diálogo que muestra la función.
if(!isFinishing())
showDialog();
con esta idea de variables globales, guardé la instancia de MainActivity en onCreate (); Variable global de Android
public class ApplicationController extends Application {
public static MainActivity this_MainActivity;
}
y un diálogo Abrir como este. funcionó.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Global Var
globals = (ApplicationController) this.getApplication();
globals.this_MainActivity = this;
}
y en un hilo, abro un diálogo como este.
AlertDialog.Builder alert = new AlertDialog.Builder(globals.this_MainActivity);
- Abrir MainActivity
- Comience un hilo.
- Abra el diálogo desde el hilo -> trabajo.
- Haga clic en el "botón Atrás" (se llamará aCreate y elimine la primera actividad principal)
- Nueva actividad principal comenzará. (y guardar su instancia en globales)
- Abrir el diálogo desde el primer hilo -> se abrirá y funcionará.
:)
android.view.WindowManager$BadTokenException: Unable to add window"
Problema:
Esta excepción se produce cuando la aplicación intenta notificar al usuario desde el hilo de fondo (AsyncTask) abriendo un cuadro de diálogo.
Si está intentando modificar la interfaz de usuario desde el hilo de fondo (normalmente desde onPostExecute () de AsyncTask) y si la actividad ingresa en la etapa final, es decir, explícitamente llamar a finish (), usuario presionando Inicio o Atrás o actividad limpiada por Android, entonces usted obtener este error
Motivo:
El motivo de esta excepción es que, como dice el mensaje de excepción, la actividad ha finalizado pero está intentando mostrar un diálogo con un contexto de la actividad finalizada. Como no hay ventana para que el cuadro de diálogo muestre el tiempo de ejecución de Android arroja esta excepción.
Solución:
Use el método
isFinishing()
que Android llama para verificar si esta actividad está en proceso de finalización: ya sea una finalización explícita () o limpieza de actividad realizada por Android. Al usar este método, es muy fácil evitar abrir el diálogo desde el hilo de fondo cuando la actividad está terminando.También mantenga una
weak reference
para la actividad (y no una referencia fuerte para que la actividad pueda destruirse una vez no sea necesaria) y verifique si la actividad no termina antes de realizar cualquier UI usando esta referencia de actividad (es decir, mostrando un cuadro de diálogo).
ej .
private class chkSubscription extends AsyncTask<String, Void, String>{
private final WeakReference<login> loginActivityWeakRef;
public chkSubscription (login loginActivity) {
super();
this.loginActivityWeakRef= new WeakReference<login >(loginActivity)
}
protected String doInBackground(String... params) {
//web service call
}
protected void onPostExecute(String result) {
if(page.contains("error")) //when not subscribed
{
if (loginActivityWeakRef.get() != null && !loginActivityWeakRef.get().isFinishing()) {
AlertDialog.Builder builder = new AlertDialog.Builder(login.this);
builder.setCancelable(true);
builder.setMessage(sucObject);
builder.setInverseBackgroundForced(true);
builder.setNeutralButton("Ok",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton){
dialog.dismiss();
}
});
builder.show();
}
}
}
}
Actualización:
Tokens de ventana:
Como su nombre lo indica, un token de ventana es un tipo especial de token de Binder que el administrador de ventanas usa para identificar de manera única una ventana en el sistema. Los tokens de ventana son importantes para la seguridad porque hacen imposible que las aplicaciones maliciosas dibujen en la parte superior de las ventanas de otras aplicaciones. El administrador de ventanas protege contra esto al requerir que las aplicaciones pasen el token de la ventana de su aplicación como parte de cada solicitud para agregar o eliminar una ventana. Si los tokens no coinciden, el administrador de ventanas rechaza la solicitud y arroja una BadTokenException . Sin tokens de ventana, este paso de identificación necesario no sería posible y el administrador de ventanas no podría protegerse de las aplicaciones maliciosas.
Un escenario del mundo real:
Cuando se inicia una aplicación por primera vez, el ActivityManagerService crea un tipo especial de token de ventana denominado token de ventana de aplicación, que identifica de forma única la ventana del contenedor de nivel superior de la aplicación. El administrador de actividades proporciona este token a la aplicación y al administrador de ventanas, y la aplicación envía el token al administrador de ventanas cada vez que quiere agregar una nueva ventana a la pantalla. Esto garantiza una interacción segura entre la aplicación y el administrador de ventanas (al imposibilitar la adición de ventanas sobre otras aplicaciones), y también facilita que el administrador de actividades realice solicitudes directas al administrador de ventanas.
- primero no puede extender AsyncTask sin anular doInBackground
segundo intento de crear AlterDailog desde el constructor y luego llamar a show ().
private boolean visible = false; class chkSubscription extends AsyncTask<String, Void, String> { protected void onPostExecute(String result) { AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setCancelable(true); builder.setMessage(sucObject); builder.setInverseBackgroundForced(true); builder.setNeutralButton("Ok", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { dialog.dismiss(); } }); AlertDialog myAlertDialog = builder.create(); if(visible) myAlertDialog.show(); } @Override protected String doInBackground(String... arg0) { // TODO Auto-generated method stub return null; } } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); visible = true; } @Override protected void onStop() { visible = false; super.onStop(); }