Android 1.6: "android.вид.WindowManager$BadTokenException: невозможно добавить окно-токен null не для приложения"

Я пытаюсь открыть диалоговое окно, но каждый раз, когда я пытаюсь открыть его, он бросает это исключение:

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)

Я создаю его, позвонив showDialog С кодом на дисплее. The onCreateDialog обработчик регистрируется нормально, и я могу пройти через него без проблем, но я прикрепил его, так как кажется, что мне чего-то не хватает:

@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;      
}

чего-то не хватает? Некоторые вопросы говорили о наличии этой проблемы при создании диалога из onCreate, которым происходит потому, что действие еще не создано, но это происходит от вызова из объекта меню и appContext переменная кажется, что она правильно заполнена в отладчике.

16 ответов


вместо : Context appContext = this.getApplicationContext(); вы должны использовать указатель на действие, в котором вы находитесь (вероятно,this).

меня сегодня тоже укусили, раздражающая часть-это getApplicationContext() дословно от developer.android.com : (


вы не можете отобразить окно/диалог приложения через контекст, который не является действием. Попробуйте передать допустимую ссылку на действие


то же самое с getApplicationContext.

документы на сайте android говорят использовать его, но он не работает...грррр : - П

Так же:

dialog = new Dialog(this); 

"этот" обычно это ваша деятельность, с которой вы начинаете диалог.


документы Android предлагают использовать getApplicationContext ();

но это не будет работать вместо того, чтобы использовать вашу текущую деятельность при создании экземпляра AlertDialog.Строитель или AlertDialog или диалог...

Ex:

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

или

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

вместо getApplicationContext(), просто использовать ActivityName.this


у меня была похожая проблема, когда у меня был другой класс что-то вроде этого:

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

работал нормально большую часть времени, но иногда он разбился с той же ошибкой. Тогда я понимаю, что в MyActivity у меня было...

public class MyActivity extends Activity {
  public static Something something;

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

потому что я держал объект как static, второй запуск кода все еще содержал исходную версию объекта и, таким образом, все еще ссылался на исходный Activity, которого давно не существовало.

глупая глупая ошибка, тем более, что мне действительно не нужно было держать объект как static в первую очередь...


просто измените его на

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

вместо

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

другое решение-установить тип окна окно Система:

dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

для этого требуется SYSTEM_ALERT_WINDOW разрешение:

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

как говорят врачи:

очень немногие приложения должны использовать это разрешение; эти окна предназначены для взаимодействия на уровне системы с пользователем.

это решение, которое вы должны использовать только в том случае, если вам требуется диалог, который не подключен к действию.


не используйте getApplicationContext() при объявлении dialouge

всегда использовать this или activity.this


это сработало для меня--

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

использовать

ActivityName.this

для вложенных диалогов эта проблема очень распространена, она работает, когда

AlertDialog.Builder mDialogBuilder = new AlertDialog.Builder(MyActivity.this);

вместо

mDialogBuilder = new AlertDialog.Builder(getApplicationContext);

эта альтернатива.


вы также можете сделать это

public class Example extends Activity {
    final Context context = this;
    final Dialog dialog = new Dialog(context);
}

это работает для меня !!


Как говорится, вам нужна активность в качестве контекста для диалога, используйте " YourActivity.это" для статического контекста или проверки здесь для того, как использовать динамический в безопасном режиме


попробуйте сбросить окна

WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

не забудьте использовать разрешение 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);
//                          }
        });
    }

текст здесь:-
используйте это для получения activity контекст progressdialog

 progressdialog = new ProgressDialog(Splash.this);

или progressdialog = new ProgressDialog(this);

использовать это для получения контекста приложения для BroadcastListener не для progressdialog.

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

лучший и самый безопасный способ показать "ProgressDialog" в AsyncTask, избегая проблемы утечки памяти, - использовать "обработчик" с Looper.главный.)(

    private ProgressDialog tProgressDialog;

затем в "onCreate"

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

Теперь вы закончили с частью настройки. Теперь вызовите "showProgress ()" и "hideProgress ()" в 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);
    }