Tôi có một thiết lập đơn giản:Android đóng băng khi có một NullPointerException trong OnClickListener.onClick (các nhiệm vụ khác không thể bắt đầu)
CrashHandler
- một lớp mà thực hiệnThread.UncaughtExceptionHandler
;CrashActivity
- hoạt động có thể gửi báo cáo của người dùng;MainActivity
- ứng dụng chính mà người dùng nên tương tác.
Khi có một ngoại lệ còn tự do trong MainActivity
hoặc bất kỳ chủ đề của nó, các CrashHandler
chặn nó và tạo ra một thông báo với ý định để bắt đầu CrashActivity
:
Intent it = new Intent("CrashReporter" + SystemClock.currentThreadTimeMillis());
it.setClass(context, CrashActivity.class);
it.setFlags(it.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
Trong lúc này chương trình Android thông báo "Ứng dụng bị lỗi", người dùng nhấp vào OK, ứng dụng đã đóng, sau đó người dùng có thể nhấp vào notification
. Nếu nhấp vào notification
, CrashActivity
sẽ bắt đầu và hiển thị.
Mã này đã hoạt động trong một thời gian dài trong nhiều tình huống khác nhau (treo trên chủ đề chính, gặp sự cố trong handler
, lỗi trên nền thread
...). Tuy nhiên, gần đây tôi đã phát hiện ra rằng nó KHÔNG LÀM VIỆC nếu ngoại lệ được ném trong phương pháp OnClickListener.onClick
trong trình nghe được gắn vào một button
trong MainActivity
. Tình huống như sau:
- Tôi thực thi mã cố ý ném
NullPointerException
; CrashHandler
chặn nó và tạo mộtnotification
(được hiển thị);- Android KHÔNG hiển thị bất kỳ thư nào (ví dụ: không có "Ứng dụng bị lỗi", sẽ hiển thị);
MainActivity
bị đóng băng;- NẾU người dùng nhấp vào thông báo để khởi chạy
CrashActivity
, màn hình màu đen được hiển thị và mọi thứ bị đóng băng (hoạt động mong muốn không được hiển thị).
Logcat
cho thấy rằng có một thời gian chờ ngày khởi động, ngay cả trước khi OnCreate
hoặc bất kỳ mã của tôi:
I/ActivityManager(11826): START u0 {act=CrashHandler1196 flg=0x14000000 cmp=mycompany.myapp/.CrashActivity bnds=[0,102][720,230] (has extras)} from pid -1
W/KeyguardViewMediator(11826): verifyUnlock called when not externally disabled
W/ActivityManager(11826): Activity pause timeout for ActivityRecord{41f4d988 u0 mycompany.myapp/.MainActivity}
W/ActivityManager(11826): Launch timeout has expired, giving up wake lock!
W/ActivityManager(11826): Activity idle timeout for ActivityRecord{4225eeb8 u0 mycompany.myapp/.CrashActivity}
- Nếu trước khi nhấp vào
notification
tôi giết các ứng dụng từADB
, cácnotification
công trình hoàn hảo . Nếu trước khi nhấp vào
notification
Tôi làm cho một số nhấp chuột và cử chỉ trên ứng dụng đông lạnh, sau một vài giây tôi nhận được một thông điệp về mộtANR
:E/ActivityManager(11826): ANR in mycompany.myapp (mycompany.myapp/.MainActivity) E/ActivityManager(11826): Reason: keyDispatchingTimedOut E/ActivityManager(11826): Load: 0.63/0.57/0.49
Nếu tôi bấm "yes, giết nó", và sau đó nhấp vào
notification
, nó hoạt động hoàn hảo.- Nếu tôi thêm
System.exit
(-1) trongCrashHandler
ngay sau khi tạo thông báo, ứng dụng sẽ thoát ngay lập tức và thông báo hoạt động hoàn hảo (rất tiếc, tôi không thể sử dụng giải pháp này trong sản xuất).
Tôi có hai câu hỏi:
- Tại sao một
NullPointer exception
trongOnClickListener.onClick
không gây ứng dụng sụp đổ, thay vì đóng băng nó cùng với hệ điều hành và ngăn chặn các hoạt động khác từ khi bắt đầu? - Việc cần làm để tránh điều đó nói chung, hoặc ít nhất, làm cách nào để làm cho việc bắt đầu
CrashActivity
trong các điều kiện này?
Tôi nghĩ bạn nên đăng một số mã của mình từ ** onClick ** để chúng tôi có thể hiểu được. –