Android 1.6: "android.view.WindowManager $ BadTokenException: Tidak dapat menambahkan jendela - token null bukan untuk aplikasi"

303

Saya mencoba untuk membuka jendela dialog, tetapi setiap kali saya mencoba membukanya, ia melempar pengecualian ini:

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)

Saya membuatnya dengan menelepon showDialogdengan id tampilan. The onCreateDialoghandler log baik dan saya dapat melangkah melalui itu tanpa masalah, tapi aku sudah melekat sejak sepertinya aku kehilangan sesuatu:

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

Apakah ada sesuatu yang hilang dari ini? Beberapa pertanyaan telah berbicara tentang masalah ini saat membuat dialog dari onCreate, yang terjadi karena aktivitas belum dibuat, tetapi ini berasal dari panggilan dari objek menu, dan appContextvariabel sepertinya diisi dengan benar di debugger.

Dan Monego
sumber

Jawaban:

609

Alih-alih: Context appContext = this.getApplicationContext(); Anda harus menggunakan pointer ke aktivitas Anda (mungkin this).

Saya digigit oleh ini hari ini juga, bagian yang mengganggu getApplicationContext()adalah kata demi kata dari developer.android.com :(

Torp
sumber
2
Ini juga dilaporkan sebagai bug (meskipun bukan saat pengguna memposting pertanyaan): code.google.com/p/android/issues/detail?id=11199
Raymond Martineau
63
Kalau-kalau ini membantu siapa pun - gunakan myActivity.ini sebagai konteks Anda dalam dialog.
Rab Ross
13
Pertanyaan dan jawaban ini berusia 3 tahun dalam 2 hari. Saya masih mendapatkan reputasi, jadi saya kira Google masih belum memperbaiki dokumen mereka ...
Torp
2
Ini telah diperbaiki di ( developer.android.com/guide/topics/ui/dialogs.html )
Martin Marconcini
6
Ini adalah bulan April 2016, dan masih pengecualian ini membuat aplikasi crash pada inisiasi dialog.
Yogesh Seralia
78

Anda tidak dapat menampilkan jendela aplikasi / dialog melalui Konteks yang bukan merupakan Kegiatan. Coba lewati referensi aktivitas yang valid

Samuh
sumber
bagaimana? Saya mencoba activity.thisdan activity.getBaseContext()tetapi tidak berhasil. Ada bantuan?
Darpan
3
Mengerti. Langsung berikan nama aktivitas Anda di dalamnya. Tanpa .this.
Darpan
45

Ditto pada hal getApplicationContext.

Dokumen-dokumen di situs android mengatakan untuk menggunakannya, tetapi tidak berfungsi ... grrrrr :-P

Kerjakan saja:

dialog = new Dialog(this); 

"Ini" biasanya adalah Aktivitas Anda dari mana Anda memulai dialog.

kenyee
sumber
43

Dokumen Android menyarankan untuk menggunakan getApplicationContext ();

tetapi itu tidak akan berfungsi sebagai gantinya yang menggunakan aktivitas Anda saat ini saat instantiating AlertDialog.Builder atau AlertDialog atau Dialog ...

Ex:

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

atau

AlertDialog.Builder builder = new  AlertDialog.Builder((Your Activity).this);
Pradeep
sumber
Ini membantu saya keluar secara besar-besaran. Saya mencoba membuat dialog dari dalam dialog lain dan hanya memiliki "AlertDialog.Builder (ini);" sedang memberikan kesalahan. Terima kasih!
EHarpham
(ActivityName.this) ini sangat berguna ketika mencoba membuat dialog di dalam
onKlik
Masalah saya adalah saya membuat ProgressDialog di dalam AlertDialog di dalam Adaptor ... Saya tidak bisa membuatnya berfungsi.
Martin Erlic
17

Alih-alih getApplicationContext(), gunakan sajaActivityName.this

mahbub_siddique
sumber
13

Saya memiliki masalah serupa di mana saya memiliki kelas lain seperti ini:

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

Bekerja dengan baik sebagian besar waktu, tetapi kadang-kadang jatuh dengan kesalahan yang sama. Kemudian saya menyadari bahwa di MyActivity...

public class MyActivity extends Activity {
  public static Something something;

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

Karena saya memegang objek sebagai static, menjalankan kedua kode masih memegang versi asli objek, dan dengan demikian masih mengacu pada yang asli Activity, yang tidak ada lama.

Kesalahan bodoh konyol, terutama karena saya benar-benar tidak perlu memegang objek seperti staticdi tempat pertama ...

T.Hawk
sumber
12

Ubah saja menjadi

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

Dari pada

AlertDialog.Builder alert_Categoryitem = 
    new AlertDialog.Builder(getApplicationContext());
Satheesh
sumber
9

Solusi lain adalah dengan mengatur jenis jendela ke dialog sistem:

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

Ini membutuhkan SYSTEM_ALERT_WINDOWizin:

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

Seperti yang dikatakan para dokter:

Sangat sedikit aplikasi yang harus menggunakan izin ini; windows ini dimaksudkan untuk interaksi tingkat sistem dengan pengguna.

Ini adalah solusi yang hanya boleh Anda gunakan jika Anda membutuhkan dialog yang tidak dilampirkan pada suatu aktivitas.

Anubian Noob
sumber
Sekarang ini adalah flag yang sudah tidak digunakan lagi dari API level 26. Karena memungkinkan pengembang untuk bermain dengan jendela sistem yang tidak baik dari perspektif pengguna.
CopsOnRoad
4

Jangan gunakan getApplicationContext()saat mendeklarasikan dialog

Selalu gunakan thisatau milik Andaactivity.this

Jinu
sumber
2

Untuk dialog bersarang masalah ini sangat umum, Ini berfungsi saat

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

digunakan sebagai ganti

mDialogBuilder = new AlertDialog.Builder(getApplicationContext);

alternatif ini.

mifthi
sumber
2

Ini Berhasil untuk saya--

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

Menggunakan

ActivityName.this
Suyog Gunjal
sumber
0

Anda juga bisa melakukan ini

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

Ini berhasil bagi saya !!

Metalhead1247
sumber
0

Seperti yang dikatakan, Anda memerlukan suatu Aktivitas sebagai konteks untuk dialog, gunakan "YourActivity.this" untuk konteks statis atau periksa di sini untuk bagaimana menggunakan yang dinamis dalam mode aman

Hugo
sumber
0

Cobalah untuk mengatur ulang dialogjenis jendela ke

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

Jangan lupa untuk menggunakan izin android.permission.SYSTEM_ALERT_WINDOW

hopetribe
sumber
0
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);
//                          }
        });
    }

Teks di sini: -
gunakan ini untuk mendapatkan activitykonteksprogressdialog

 progressdialog = new ProgressDialog(Splash.this);

atau progressdialog = new ProgressDialog(this);

gunakan ini untuk mendapatkan konteks aplikasi BroadcastListener bukan untuk progressdialog.

progressdialog = new ProgressDialog(getApplicationContext());
progressdialog = new ProgressDialog(getBaseContext());
Faisal Ashraf
sumber
0

Cara terbaik dan teraman untuk menunjukkan 'ProgressDialog' di AsyncTask, menghindari masalah kebocoran memori adalah dengan menggunakan 'Handler' dengan Looper.main ().

    private ProgressDialog tProgressDialog;

lalu di 'onCreate'

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

Sekarang Anda selesai dengan bagian setup. Sekarang panggil 'showProgress ()' dan 'hideProgress ()' di 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);
    }
Sankar Behera
sumber