Android 1.6: "android.vue.WindowManager $ BadTokenException: impossible d'ajouter window-token null n'est pas pour une application"
j'essaie 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 le crée en appelant showDialog
avec l'identifiant de l'écran. Le gestionnaire onCreateDialog
se connecte très bien et je peux passer à travers sans problème, mais je l'ai attaché car 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;
}
il manque quelque chose? Certaines questions ont parlé d'avoir ce problème quand créer une boîte de dialogue à partir de onCreate
, ce qui arrive parce que l'activité n'est pas encore créée, mais cela vient d'un appel d'un objet menu, et la variable appContext
semble être correctement générée dans le débogueur.
16 réponses
au lieu de :
Context appContext = this.getApplicationContext();
vous devriez utiliser un pointeur vers l'activité dans laquelle vous êtes (probablement this
).
j'ai été mordu par ceci aujourd'hui aussi, la partie ennuyeuse est le getApplicationContext()
est mot à mot de developer.android.com : (
vous ne pouvez pas afficher une fenêtre/dialogue d'application à travers un contexte qui n'est pas une activité. Essayez de passer une référence d'activité valide
idem sur le truc du context getapplication.
les documents sur le site android dit de l'utiliser, mais il ne fonctionne pas...grrrrrrr: - p
Just do:
dialog = new Dialog(this);
"ce" est généralement de votre Activité à partir de laquelle vous lancez la boîte de dialogue.
Android documents suggère d'utiliser getApplicationContext ();
mais il ne fonctionnera pas à la place de que l'utilisation de votre activité actuelle tout en instantiating AlertDialog.Constructeur 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'avais une autre classe quelque chose 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();
}
}
fonctionnait bien la plupart du temps, mais parfois il s'est écrasé avec la même erreur. Puis je me rends compte que dans MyActivity
j'avais...
public class MyActivity extends Activity {
public static Something something;
public void someMethod() {
if (something==null) {
something=new Something(this);
}
}
}
parce que je tenais l'objet comme static
, un deuxième passage du code tenait toujours la version originale de l'objet, et donc se référait toujours à l'original Activity
, qui ne fut pas long exister.
Stupide erreur, d'autant plus que je n'avais pas vraiment besoin de tenir l'objet comme static
en premier lieu...
il suffit de le changer en
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 dans une boîte de dialogue Système:
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
cela nécessite la SYSTEM_ALERT_WINDOW
permission:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
comme disent les docs:
très peu d'applications doivent utiliser cette permission; ces fenêtres sont destinées à une interaction au niveau du système avec l'utilisateur.
Cette solution ne doit être utilisée que si vous avez besoin d'un dialogue qui n'est pas attaché à une activité.
Ne pas utiliser getApplicationContext()
, déclarant dialouge
utilisez toujours this
ou votre activity.this
ça 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();
Utiliser
ActivityName.this
pour dialogues emboîtés ce problème est très courant, il fonctionne quand
AlertDialog.Builder mDialogBuilder = new AlertDialog.Builder(MyActivity.this);
est utilisé à la place 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);
}
ça a marché pour moi !!
essayer de réinitialiser dialog
type de fenêtre à
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
N'oubliez pas d'utiliser la permission 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);
// }
});
}
ici le Texte:-
utilisez ceci pour obtenir le contexte activity
pour progressdialog
progressdialog = new ProgressDialog(Splash.this);
ou progressdialog = new ProgressDialog(this);
utilisez ceci pour obtenir le contexte d'application pour BroadcastListener
pas pour progressdialog
.
progressdialog = new ProgressDialog(getApplicationContext());
progressdialog = new ProgressDialog(getBaseContext());
la meilleure et la plus sûre façon de montrer un 'ProgressDialog' dans un AsyncTask, en évitant le problème de fuite de mémoire est d'utiliser un 'Handler' avec Looper.principal.)(
private ProgressDialog tProgressDialog;
puis dans le "onCreate "
tProgressDialog = new ProgressDialog(this);
tProgressDialog.setMessage(getString(R.string.loading));
tProgressDialog.setIndeterminate(true);
Maintenant vous avez fini avec la partie setup. 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);
}