Android 1.6: « android.view.WindowManager $ BadTokenException: Impossible de fenêtre ajouter - null jeton n'est pas pour une application »
-
26-09-2019 - |
Question
Je suis en train d'ouvrir une fenêtre de dialogue, mais chaque fois que j'essaie de l'ouvrir, il lance cette exception:
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)
Je crée en appelant showDialog
avec l'identifiant de l'écran. Le gestionnaire de onCreateDialog
enregistre bien et je peux parcourir sans un problème, mais je l'ai attaché depuis il semble que je manque quelque chose:
@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;
}
Y at-il quelque chose manque à ce sujet? Certaines questions ont parlé d'avoir ce problème lors de la création d'un dialogue à partir onCreate
, ce qui arrive parce que l'activité est pas encore créé, mais cela provient d'un appel d'un objet de menu, et la variable appContext
semble comme il est rempli correctement dans le débogueur.
La solution
Au lieu de:
Context appContext = this.getApplicationContext();
vous devez utiliser un pointeur sur l'activité que vous êtes (probablement this
).
Je me suis mordue par aujourd'hui aussi, la partie ennuyeuse est le getApplicationContext()
est mot pour mot de developer.android.com: (
Autres conseils
Vous ne pouvez pas afficher une fenêtre de l'application / dialogue dans un contexte qui n'est pas une activité. Essayez de passer une référence d'activité valide
Même chose sur la chose getApplicationContext.
Les documents sur le site Android dit à l'utiliser, mais il ne fonctionne pas ... Grrrrr :-P
Il suffit de faire:
dialog = new Dialog(this);
"ce" est habituellement votre activité à partir de laquelle vous démarrez la boîte de dialogue.
documents Applications suggère d'utiliser getApplicationContext ();
mais il ne fonctionnera pas au lieu de cette utilisation votre activité actuelle lors de l'instanciation AlertDialog.Builder ou AlertDialog ou Dialog ...
Ex:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
ou
AlertDialog.Builder builder = new AlertDialog.Builder((Your Activity).this);
Au lieu de getApplicationContext()
, il suffit d'utiliser ActivityName.this
J'ai eu un problème similaire où j'ai eu une autre chose de classe comme ceci:
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();
}
}
a bien fonctionné la plupart du temps, mais parfois il est écrasé avec la même erreur. Ensuite, je me rends compte que MyActivity
I had ...
public class MyActivity extends Activity {
public static Something something;
public void someMethod() {
if (something==null) {
something=new Something(this);
}
}
}
Parce que je retenais l'objet comme static
, une deuxième manche du code tenait toujours la version originale de l'objet, et donc était encore référence à la Activity
d'origine, qui n'existent depuis longtemps.
idiot erreur stupide, d'autant plus que je ne l'ai pas vraiment besoin d'être maintenant l'objet comme static
en premier lieu ...
Il suffit de changer dans
AlertDialog.Builder alert_Categoryitem =
new AlertDialog.Builder(YourActivity.this);
Au lieu de
AlertDialog.Builder alert_Categoryitem =
new AlertDialog.Builder(getApplicationContext());
Une autre solution consiste à définir le type de fenêtre pour une fenêtre de dialogue du système:
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
Cela nécessite l'autorisation SYSTEM_ALERT_WINDOW
:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
Comme les docs disent:
Très peu d'applications devraient utiliser cette autorisation; ces fenêtres sont destinées à une interaction au niveau du système avec l'utilisateur.
Ceci est une solution que vous ne devez utiliser si vous avez besoin d'une boîte de dialogue qui n'est pas attaché à une activité.
Ne pas utiliser getApplicationContext()
sur la déclaration Dialouge
Toujours utiliser this
ou votre activity.this
a marché pour moi -
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();
Utilisez
ActivityName.this
Pour les dialogues imbriqués ce problème est très fréquent, il fonctionne quand
AlertDialog.Builder mDialogBuilder = new AlertDialog.Builder(MyActivity.this);
est utilisé au lieu de
mDialogBuilder = new AlertDialog.Builder(getApplicationContext);
cette alternative.
Vous pouvez aussi le faire
public class Example extends Activity {
final Context context = this;
final Dialog dialog = new Dialog(context);
}
Cela a fonctionné pour moi !!
Comme on dit, vous avez besoin d'une activité comme contexte pour la boîte de dialogue, utilisez « YourActivity.this » pour un contexte statique ou consultez ici pour savoir comment utiliser une de dynamique dans un mode sans échec
Essayez de réinitialiser le type de fenêtre dialog
à
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
Ne pas oublier d'utiliser le android.permission.SYSTEM_ALERT_WINDOW
d'autorisation
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);
// }
});
}
Texte ici: -
utiliser pour obtenir le contexte de activity
pour progressdialog
progressdialog = new ProgressDialog(Splash.this);
ou progressdialog = new ProgressDialog(this);
utiliser pour obtenir ce contexte d'application pour BroadcastListener
pas progressdialog
.
progressdialog = new ProgressDialog(getApplicationContext());
progressdialog = new ProgressDialog(getBaseContext());
La meilleure et la meilleure façon de montrer un « ProgressDialog » dans un AsyncTask, évitant problème de fuite de mémoire est d'utiliser un « gestionnaire » avec Looper.main ().
private ProgressDialog tProgressDialog;
puis dans le 'onCreate'
tProgressDialog = new ProgressDialog(this);
tProgressDialog.setMessage(getString(R.string.loading));
tProgressDialog.setIndeterminate(true);
Maintenant, vous r fait avec la partie de l'installation. Maintenant, appelez 'ShowProgress ()' et 'hideProgress ()' dans 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);
}