Android: ProgressDialog.show () mengalami error dengan getApplicationContext

109

Saya tidak bisa memahami mengapa ini terjadi. Kode ini:

mProgressDialog = ProgressDialog.show(this, "", getString(R.string.loading), true);

bekerja dengan baik. Namun, kode ini:

mProgressDialog = ProgressDialog.show(getApplicationContext(), "", getString(R.string.loading), true);

melempar pengecualian berikut:

W/WindowManager(  569): Attempted to add window with non-application token WindowToken{438bee58 token=null}.  Aborting.
D/AndroidRuntime( 2049): Shutting down VM
W/dalvikvm( 2049): threadid=3: thread exiting with uncaught exception (group=0x4001aa28)
E/AndroidRuntime( 2049): Uncaught handler: thread main exiting due to uncaught exception
E/AndroidRuntime( 2049): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.tastekid.TasteKid/com.tastekid.TasteKid.YouTube}: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
E/AndroidRuntime( 2049):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2401)
E/AndroidRuntime( 2049):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2417)
E/AndroidRuntime( 2049):    at android.app.ActivityThread.access$2100(ActivityThread.java:116)
E/AndroidRuntime( 2049):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1794)
E/AndroidRuntime( 2049):    at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime( 2049):    at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime( 2049):    at android.app.ActivityThread.main(ActivityThread.java:4203)
E/AndroidRuntime( 2049):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 2049):    at java.lang.reflect.Method.invoke(Method.java:521)
E/AndroidRuntime( 2049):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
E/AndroidRuntime( 2049):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549)
E/AndroidRuntime( 2049):    at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime( 2049): Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
E/AndroidRuntime( 2049):    at android.view.ViewRoot.setView(ViewRoot.java:460)
E/AndroidRuntime( 2049):    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
E/AndroidRuntime( 2049):    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
E/AndroidRuntime( 2049):    at android.app.Dialog.show(Dialog.java:238)
E/AndroidRuntime( 2049):    at android.app.ProgressDialog.show(ProgressDialog.java:107)
E/AndroidRuntime( 2049):    at android.app.ProgressDialog.show(ProgressDialog.java:90)
E/AndroidRuntime( 2049):    at com.tastekid.TasteKid.YouTube.onCreate(YouTube.java:45)
E/AndroidRuntime( 2049):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
E/AndroidRuntime( 2049):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2364)
E/AndroidRuntime( 2049):    ... 11 more

Ada ide mengapa ini terjadi? Saya memanggil ini dari onCreatemetode.

Felix
sumber
Jika Anda menggunakan Fragment, stackoverflow.com/questions/24825114/…
Yeo

Jawaban:

42

Versi API mana yang Anda gunakan? Jika saya benar tentang masalahnya maka ini telah diperbaiki di Android 1.6 (API versi 4).

Sepertinya referensi objek yang getApplicationContext()mengembalikan hanya menunjuk ke nol. Saya pikir Anda mengalami masalah yang mirip dengan yang saya alami di mana beberapa kode di onCreate()sedang dijalankan sebelum jendela benar-benar selesai dibangun. Ini akan menjadi peretasan, tetapi coba luncurkan Thread baru dalam beberapa ratus milidetik (IIRC: 300-400 tampaknya berfungsi untuk saya, tetapi Anda harus mengotak-atik) yang membuka ProgressDialog Anda dan memulai apa pun yang Anda butuhkan ( mis. jaringan IO). Sesuatu seperti ini:

@Override
public void onCreate(Bundle savedInstanceState) {
    // do all your other stuff here

    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            mProgressDialog = ProgressDialog.show(
               YouTube.this.getApplicationContext(), "",
               YouTube.this.getString(R.string.loading), true);

            // start time consuming background process here
        }
    }, 1000); // starting it in 1 second
}
Jeremy Logan
sumber
6
Saya menggunakan 1.6. Saya cukup yakin setiap operasi UI harus dilakukan di thread UI, sehingga memanggil ProgressDialog.show () di thread terpisah bisa dengan mudah menjadi masalah besar. Masih menganggap ini aneh.
Felix
3
Dalam contoh yang saya berikan kepada Anda tidak melakukan operasi UI di utas lain, utas lain hanya memanggil kembali ke utas UI yang menyuruhnya membuka dialog.
Jeremy Logan
Ini benar-benar aneh dan ini benar-benar peretasan, tetapi berhasil untuk saya. Saya perlu menguji bug yang saya alami di 1.6 untuk melihat apakah saya dapat BERHENTI menggunakan ini.
Jeremy Logan
1
Ini tidak 'aneh' juga bukan 'peretasan total', itu pendekatan yang sangat sah!
KomodoDave
1
@Komodo Saya baru menyadari bahwa saya memiliki masalah yang sama. Namun, peretasan buruk ada di timer. Ini adalah jendela waktu yang menunggu untuk gagal sewaktu-waktu dalam beberapa situasi. Kunci sukses mungkin dalam mengatur timer yang lebih pendek, periksa untuk melihat apakah aplikasi sudah siap, ulangi tindakan sampai selesai. Mungkin juga membatasi berapa kali mencoba.
Jim Rush
129

Saya menggunakan Android versi 2.1 dengan API Level 7. Saya menghadapi masalah ini (atau serupa) dan diselesaikan dengan menggunakan ini:

Dialog dialog = new Dialog(this);

alih-alih ini:

Dialog dialog = new Dialog(getApplicationContext());

Semoga ini membantu :)

Taner
sumber
4
Saya memiliki masalah serupa, tetapi menggunakan ActivityGroup. Satu-satunya cara saya bisa mengatasi kesalahan ini adalah dengan menggunakan getParent () sebagai gantinya.
brack
20
Bagaimana ini menjawab pertanyaannya? Dia bertanya MENGAPA yang kedua tidak bekerja, sedangkan yang pertama berhasil.
Burkhard
3
-1, 'this' sama dengan 'getApplicationContext ()' bagi sebagian dari kita.
kellogs
Masih tip berguna yang berkembang untuk 2.1
Carlos P
64

Bagi saya bekerja berubah

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

untuk

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

Hal yang aneh adalah bahwa yang pertama dapat ditemukan di tutorial google dan orang-orang mendapatkan kesalahan ini ..

wtk
sumber
1
satu-satunya solusi yang berfungsi untuk saya dengan peringatan di dalam acara onclick
Tobias
Ini adalah cara yang benar untuk melakukannya. Jangan pernah menggunakan ApplicationContext kecuali benar-benar diperlukan dan yang terpenting, jangan pernah menggunakannya untuk menampilkan elemen UI. Itulah gunanya aktivitas (dan akhirnya fragmen).
Martin Marconcini
Ini adalah salah satunya. thissemua saja tidak akan berfungsi jika Anda melakukannya di dalam, misalnya, click listener.
Ayman Salah
23

Saya tidak berpikir ini adalah masalah waktu di sekitar konteks aplikasi null

Coba perluas Aplikasi dalam aplikasi Anda (atau gunakan saja jika Anda sudah memilikinya)

public class MyApp extends Application

Jadikan instance tersedia sebagai singleton pribadi. Ini tidak pernah nol

private static MyApp appInstance;

Buat pembantu statis di MyApp (yang akan menggunakan singleton)

    public static void showProgressDialog( CharSequence title, CharSequence message )
{
    prog = ProgressDialog.show(appInstance, title, message, true); // Never Do This!
}

LEDAKAN!!

Juga, lihat jawaban insinyur android di sini: WindowManager $ BadTokenException

Salah satu penyebab kesalahan ini mungkin mencoba menampilkan jendela / dialog aplikasi melalui Konteks yang bukan merupakan Aktivitas.

Sekarang, saya setuju, tidak masuk akal bahwa metode ini mengambil parameter Konteks, bukan Aktivitas ..

alienjazzcat.dll
sumber
10

Setelah membaca jawaban di atas, saya menemukan bahwa untuk situasi saya, masalah berikut ini diperbaiki.

Ini melemparkan kesalahan

myButton.setOnClickListener(new OnClickListener(){
    public void onClick(View v) {
        MyDialogue dialog = new MyDialogue(getApplicationContext());
        dialog.show();              
    }
});

Berdasarkan jawaban sebelumnya yang menyarankan bahwa konteksnya salah, saya mengubah getApplicationContext () untuk mengambil konteks dari Tampilan yang diteruskan ke metode tombol onClick.

myButton.setOnClickListener(new OnClickListener(){
    public void onClick(View v) {
        MyDialogue dialog = new MyDialogue(v.getContext());
        dialog.show();              
    }
});

Saya tidak sepenuhnya memahami cara kerja Java jadi saya bisa saja salah, tapi saya menduga bahwa untuk situasi spesifik saya penyebabnya bisa jadi terkait dengan fakta bahwa potongan di atas didefinisikan dalam kelas Aktivitas Abstrak; diwariskan dan digunakan oleh banyak Aktivitas, mungkin itu berkontribusi pada fakta bahwa getApplicationContext () tidak mengembalikan konteks yang valid ?? (Hanya tebakan).

Emile
sumber
Solusi dengan skor yang lebih baik mungkin bekerja untuk sebagian besar kasus, tetapi teknik v.getContext () Anda tampaknya menyelesaikan kasus yang paling membandel seperti saya. Pengetahuan empiris java saya membuat saya berpikir bahwa konteks yang berasal dari metode onCreated tidak persis sama dengan konteks yang berasal dari View of an onClick method. Beri suara!
Josh
Ini menyelamatkan hariku!
Alejandro Luengo
6

Saya membuat tampilan peta dengan overlay yang diperinci. Saya membuat overlay terperinci seperti ini dari mapActivity saya:

OCItemizedOverlay currentLocationOverlay = new OCItemizedOverlay(pin,getApplicationContext);

Saya menemukan bahwa saya akan mendapatkan pengecualian "android.view.WindowManager $ BadTokenException: Tidak dapat menambahkan window - token null bukan untuk aplikasi" ketika metode onTap itemizedoverlay saya dipicu (ketika lokasi diketuk pada mapview).

Saya menemukan bahwa jika saya meneruskan, 'this' alih-alih 'getApplicationContext ()' ke konstruktor saya, masalahnya hilang. Ini sepertinya mendukung kesimpulan alienjazzcat. aneh.

sandi
sumber
1
Terima kasih, inilah masalah saya.
Kon
4

Untuk Aktivitas yang ditampilkan dalam TabActivities gunakan getParent ()

final AlertDialog.Builder builder = new AlertDialog.Builder(getParent());

dari pada

final AlertDialog.Builder builder = new AlertDialog.Builder(this);
salcosand.dll
sumber
3

Untuk Android 2.2
Gunakan kode ini:

//activity is an instance of a class which extends android.app.Activity
Dialog dialog = new Dialog(activity);

alih-alih kode ini:

// this code produces an ERROR:
//android.view.WindowManager$BadTokenException: 
//Unable to add window -- token null is not for an application
Context mContext = activity.getApplicationContext();
Dialog dialog = new Dialog(mContext);

Catatan: Dialog kustom saya dibuat di luar activity.onCreateDialog(int dialogId)metode.

jm_java
sumber
3

Coba -

AlertDialog.Builder builder = new AlertDialog.Builder(getParent());
eyal
sumber
Diperlukan ketika aktivitas saat ini berada di dalam grup aktivitas
htafoya
2

Memiliki masalah yang sama dengan (kompatibilitas) Fragmen di mana menggunakan getActivity()dalam membuat ProgressDialog.show()crash itu. Saya setuju bahwa itu karena waktu.

Perbaikan yang mungkin:

mContext = getApplicationContext();

if (mContext != null) {
    mProgressDialog = ProgressDialog.show(mContext, "", getString(R.string.loading), true);
}

alih-alih menggunakan

mProgressDialog = ProgressDialog.show(getApplicationContext(), "", getString(R.string.loading), true);

Tempatkan mContext sedini mungkin untuk memberinya lebih banyak waktu untuk mengambil konteks. Masih belum ada jaminan bahwa ini akan berhasil, ini hanya mengurangi kemungkinan crash. Jika masih tidak berhasil, Anda harus menggunakan peretasan pengatur waktu (yang dapat menyebabkan masalah waktu lain seperti menutup dialog nanti).

Tentunya kalau bisa pakai thisor ActivityName.this, lebih stabil karena thissudah menunjuk ke sesuatu. Namun dalam beberapa kasus, seperti pada arsitektur Fragmen tertentu, ini bukanlah suatu pilihan.

Muz
sumber
2

(Untuk referensi di masa mendatang)

Saya pikir itu karena ada perbedaan Konteks Aplikasi dan Konteks Aktivitas, seperti yang dijelaskan di sini: http://www.doubleencore.com/2013/06/context/

Artinya kita tidak bisa menampilkan dialog menggunakan Application Context. Itu dia.

vtloc
sumber
2

Untuk menggunakan dialog di dalam aktivitas, lakukan dengan cara ini:

private Context mContext;
private AlertDialog.Builder mBuilder;

@Override
protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     mContext = this;

     //using mContext here refering to activity context
     mBuilder = new AlertDialog.Builder(mContext);
     //...
     //rest of the code
     //...
}

Untuk menggunakan dialog di dalam fragmen, lakukan dengan cara ini:

private Context mContext;
private AlertDialog.Builder mBuilder;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
      View mRootView = inflater.inflate(R.layout.fragment_layout, container, false);
      mContext = getActivity();

      //using mContext here refering to fragment's hosting activity context
      mBuilder = new AlertDialog.Builder(mContext);
      //...
      //rest of the code
      //...
      return mRootView;
}

Itu dia ^ _ ^

blueware
sumber
1

Apa yang saya lakukan untuk menyiasati ini adalah membuat kelas dasar untuk semua aktivitas saya tempat saya menyimpan data global. Pada aktivitas pertama, saya menyimpan konteks dalam variabel di kelas dasar saya seperti ini:

Kelas Dasar

public static Context myucontext; 

Aktivitas Pertama berasal dari Kelas Dasar

mycontext = this

Kemudian saya menggunakan mycontext daripada getApplicationContext saat membuat dialog.

AlertDialog alertDialog = new AlertDialog.Builder(mycontext).create();
pondok hujan
sumber
Sayangnya solusi ini tidak mendapatkan suara positif lagi. Dari semua solusi yang mungkin disajikan di sini, ini adalah satu-satunya hal yang berhasil untuk saya di AsyncTask
ckn
1

Jika Anda memanggil ProgressDialog.show () dalam sebuah fragmen, mentransmisikan mContext ke Activity berhasil untuk saya.

     ProgressDialog pd = new ProgressDialog((Activity) mContext);
Dale Julian
sumber
1

Ini masalah umum. Gunakan thisalih-alih getApplicationContext() Itu seharusnya menyelesaikan masalah Anda

Atul Kumar
sumber
0

Saya telah mengimplementasikan Dialog Peringatan untuk pengecualian dengan tampilan aktif saat ini. Setiap kali saya memberikan seperti ini

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

Diberikan Pengecualian Jendela yang sama. Saya menulis kode untuk peringatan dari onCreate (). Begitu sederhana saya gunakan context = this;setelah setContentView()pernyataan dalam onCreate()metode. Mengambil variabel konteks sebagai global likeContext context;

Contoh kode adalah

static Context context;

 public void onCreate(Bundle savedInstanceState)  { 
        super.onCreate(savedInstanceState); 


        setContentView(R.layout.network); 
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        context = this;
.......

Contoh Metode Peringatan adalah

private void alertException(String execMsg){
        Log.i(TAG,"in alertException()..."+context);
        Log.e(TAG,"Exception :"+execMsg);
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
.......

Ini berfungsi dengan baik untuk saya Sebenarnya saya mencari kesalahan ini di StackOverflow saya menemukan kueri ini.Setelah membaca semua tanggapan dari posting ini, saya mencoba cara ini agar berhasil.Saya pikir ini adalah solusi sederhana untuk mengatasi pengecualian.

Terima kasih, Rajendar

Rajendar
sumber
0

jika Anda memiliki masalah pada groupActivity jangan gunakan ini. PARENT adalah statis dari Parent ActivityGroup.

final AlertDialog.Builder builder = new AlertDialog.Builder(GroupActivityParent.PARENT);

dari pada

final AlertDialog.Builder builder = new AlertDialog.Builder(getParent());
vilvestre.dll
sumber