Saya ingin menyetel pengendali pengecualian tak tertangkap global untuk semua utas dalam aplikasi Android saya. Jadi, di Application
subclass saya, saya menetapkan implementasi Thread.UncaughtExceptionHandler
sebagai pengendali default untuk pengecualian yang tidak tertangkap.
Thread.setDefaultUncaughtExceptionHandler(
new DefaultExceptionHandler(this));
Dalam implementasinya, saya mencoba untuk AlertDialog
menampilkan pesan pengecualian yang sesuai.
Namun, ini sepertinya tidak berhasil. Setiap kali, pengecualian dilemparkan untuk utas apa pun yang tidak tertangani, saya mendapatkan stok, dialog OS-default ("Maaf! -Application-has-stop-terduga dialog").
Apa cara yang benar dan ideal untuk menyetel penangan default untuk pengecualian yang tidak tertangkap?
Jawaban:
Seharusnya hanya itu yang perlu Anda lakukan. (Pastikan Anda menghentikan proses setelah itu - keadaan bisa jadi tidak pasti.)
Hal pertama yang harus diperiksa adalah apakah penangan Android masih dipanggil. Ada kemungkinan bahwa versi Anda dipanggil tetapi gagal fatal dan system_server menampilkan dialog umum ketika melihat proses macet.
Tambahkan beberapa pesan log di bagian atas penangan Anda untuk melihat apakah itu sampai di sana. Cetak hasil dari getDefaultUncaughtExceptionHandler, lalu lemparkan pengecualian yang tidak tertangkap yang menyebabkan error. Pantau keluaran logcat untuk melihat apa yang terjadi.
sumber
Saya memposting solusi sederhana untuk penanganan khusus Android crash sejak lama. Ini sedikit hacky namun bekerja pada semua versi Android (termasuk Lollipop).
Pertama, sedikit teori. Masalah utama saat Anda menggunakan pengendali pengecualian tidak tertangkap di Android datang dengan pengecualian yang dilemparkan di utas utama (alias UI). Dan inilah alasannya. Saat aplikasi memulai sistem memanggil metode ActivityThread.main yang mempersiapkan dan memulai looper utama aplikasi Anda:
public static void main(String[] args) { … … Looper.prepareMainLooper(); … Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }
Looper utama bertanggung jawab untuk memproses pesan yang diposting di thread UI (termasuk semua pesan yang terkait dengan rendering dan interaksi UI). Jika pengecualian dilempar di thread UI, itu akan ditangkap oleh penangan pengecualian Anda, tetapi karena Anda keluar dari
loop()
metode, Anda tidak akan dapat menampilkan dialog atau aktivitas apa pun kepada pengguna karena tidak ada yang tersisa untuk memproses pesan UI untukmu.Solusi yang diusulkan cukup sederhana. Kami menjalankan
Looper.loop
metode sendiri dan mengelilinginya dengan blok coba-tangkap. Saat pengecualian tertangkap, kami memprosesnya sesuai keinginan (misalnya memulai aktivitas laporan kustom kami) dan memanggilLooper.loop
metode lagi.Metode berikut mendemonstrasikan teknik ini (harus dipanggil dari
Application.onCreate
pendengar):private void startCatcher() { UncaughtExceptionHandler systemUncaughtHandler = Thread.getDefaultUncaughtExceptionHandler(); // the following handler is used to catch exceptions thrown in background threads Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler(new Handler())); while (true) { try { Looper.loop(); Thread.setDefaultUncaughtExceptionHandler(systemUncaughtHandler); throw new RuntimeException("Main thread loop unexpectedly exited"); } catch (Throwable e) { showCrashDisplayActivity(e); } } }
Seperti yang Anda lihat, penangan pengecualian tak tertangkap hanya digunakan untuk pengecualian yang dilemparkan di utas latar belakang. Penangan berikut menangkap pengecualian tersebut dan menyebarkannya ke UI thread:
static class UncaughtHandler implements UncaughtExceptionHandler { private final Handler mHandler; UncaughtHandler(Handler handler) { mHandler = handler; } public void uncaughtException(Thread thread, final Throwable e) { mHandler.post(new Runnable() { public void run() { throw new BackgroundException(e); } }); } }
Contoh proyek yang menggunakan teknik ini tersedia di repo GitHub saya: https://github.com/idolon-github/android-crash-catcher
sumber
java.lang.RuntimeException: Performing pause of activity that is not resumed
. Saya yakin ketika saya mencoba memulai looper saya sendiri, sistem akan menjeda aktivitas yang akan segera dimulai? Saya tidak yakin tetapi bantuan apa pun akan dihargai. Terima kasihSaya pikir untuk menonaktifkannya dalam metode uncaughtException () jangan panggil beforeHandler.uncaughtException () di mana beforeHandler ditetapkan oleh
previousHandler = Thread.getDefaultUncaughtExceptionHandler();
sumber
FWIW Saya tahu ini sedikit di luar topik, tetapi kami telah menggunakan paket gratis Crittercism dengan sukses. Mereka juga menawarkan beberapa fitur premium, seperti menangani pengecualian sehingga aplikasi tidak macet.
Dalam versi gratis, pengguna masih melihat kerusakan, tetapi setidaknya saya mendapatkan email dan pelacakan tumpukan.
Kami juga menggunakan versi iOS (tetapi saya telah mendengar dari kolega saya bahwa versi ini kurang bagus).
Berikut pertanyaan serupa:
sumber
Ini tidak bekerja sampai Anda menelepon
android.os.Process.killProcess(android.os.Process.myPid());
di akhir UncaughtExceptionHandler Anda.
sumber