有時候由于測試不充分或者程式潛在的問題而導緻程式異常崩潰,這個是令人無法接受的,在android中怎樣捕獲程式的異常崩潰,然後進行一些必要的處理或重新啟動
應用這個問題困惱了我很久,今天終于解決了該問題,寫篇文章記錄一下。
首先捕獲程式崩潰的異常就必須了解一下java中uncaughtexceptionhandler這個接口,android沿用了此接口,在android api中:
通過實作此接口,能夠處理線程被一個無法捕捉的異常所終止的情況。如上所述的情況,handler将會報告線程終止和不明原因異常這個情況,如果沒有自定義handler,
線程管理組就被預設為報告異常的handler。
threadgroup 這個類就是實作了uncaughtexceptionhandler這個接口,如果想捕獲異常我們可以實作這個接口或者繼承threadgroup,并重載uncaughtexception方法。
在java api中對該接口描述的更詳細:
我就不翻譯了,太吃力了....%>_<%。在實作uncaughtexceptionhandler時,必須重載uncaughtexception(thread thread, throwable ex) ,如果我們沒有實作該接口
也就是沒有顯示捕捉異常,則ex為空,否則ex不為空,thread 則為出異常的線程。
接下來上代碼,實作uncaughtexceptionhandler接口,顯示處理線程異常終止的情況:
public class uncehandler implements uncaughtexceptionhandler {
private thread.uncaughtexceptionhandler mdefaulthandler;
public static final string tag = "catchexcep";
catchexcep application;
public uncehandler(catchexcep application){
//擷取系統預設的uncaughtexception處理器
mdefaulthandler = thread.getdefaultuncaughtexceptionhandler();
this.application = application;
}
@override
public void uncaughtexception(thread thread, throwable ex) {
if(!handleexception(ex) && mdefaulthandler != null){
//如果使用者沒有處理則讓系統預設的異常處理器來處理
mdefaulthandler.uncaughtexception(thread, ex);
}else{
try{
thread.sleep(2000);
}catch (interruptedexception e){
log.e(tag, "error : ", e);
}
intent intent = new intent(application.getapplicationcontext(), mainactivity.class);
pendingintent restartintent = pendingintent.getactivity(
application.getapplicationcontext(), 0, intent,
intent.flag_activity_new_task);
//退出程式
alarmmanager mgr = (alarmmanager)application.getsystemservice(context.alarm_service);
mgr.set(alarmmanager.rtc, system.currenttimemillis() + 1000,
restartintent); // 1秒鐘後重新開機應用
application.finishactivity();
}
/**
* 自定義錯誤處理,收集錯誤資訊 發送錯誤報告等操作均在此完成.
*
* @param ex
* @return true:如果處理了該異常資訊;否則傳回false.
*/
private boolean handleexception(throwable ex) {
if (ex == null) {
return false;
//使用toast來顯示異常資訊
new thread(){
@override
public void run() {
looper.prepare();
toast.maketext(application.getapplicationcontext(), "很抱歉,程式出現異常,即将退出.",
toast.length_short).show();
looper.loop();
}
}.start();
return true;
}
}
public class catchexcep extends application{
arraylist<activity> list = new arraylist<activity>();
public void init(){
//設定該crashhandler為程式的預設處理器
uncehandler catchexcep = new uncehandler(this);
thread.setdefaultuncaughtexceptionhandler(catchexcep);
/**
* activity關閉時,删除activity清單中的activity對象*/
public void removeactivity(activity a){
list.remove(a);
* 向activity清單中添加activity對象*/
public void addactivity(activity a){
list.add(a);
* 關閉activity清單中的所有activity*/
public void finishactivity(){
for (activity activity : list) {
if (null != activity) {
activity.finish();
}
}
//殺死該應用程序
android.os.process.killprocess(android.os.process.mypid());
然後人為制造一個異常:
button btn;
textview tv;
private catchexcep application;
protected void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.activity_main);
btn = (button)findviewbyid(r.id.btn);
tv = (textview)findviewbyid(r.id.tv);
application = (catchexcep)getapplication();
application.init();
application.addactivity(this);
btn.setonclicklistener(this);
}
* 人為制造的異常*/
public void press(){
new thread(new runnable() {
@override
public void run() {
tv.settext("dfsd");
}
}).start();
public void onclick(view v) {
press();
上訴代碼就能夠實作 應用出現無法捕捉的異常時,殺死目前程序,重新啟動一個應用。
我之前困擾的地方:搜了很多資料,殺死異常程序,重新啟動應用,網上應用都是通過application對象調用startactivity(intent),然後殺死異常程序。但是我怎樣試都不成功,
程序是殺死了,但是應用卻沒啟動起來,如果不将異常程序殺死,那麼關閉應用時就得關閉兩次,顯然不能夠接受。網上的一些方法都是錯誤的:如下幾篇部落格:
<a target="_blank" href="http://blog.csdn.net/xianming01/article/details/7711160">http://blog.csdn.net/xianming01/article/details/7711160</a>
<a target="_blank" href="http://blog.csdn.net/ryantang03/article/details/9336295?reload">http://blog.csdn.net/ryantang03/article/details/9336295?reload</a>
他們的方法能夠捕獲異常,殺死異常程序,但是卻不能夠重新啟動應用。
如何殺死異常程序,重新開機應用,就得使用pendingintent,這個類是android中對intent類的包裝,具體了解我會在寫一篇部落格,自己也可以去檢視android api。
通過alarmmanager 啟動它,并且關閉打開的activity殺死異常程序就能夠實作重新啟動應用。
參考連結:
<a target="_blank" href="http://zheyiw.iteye.com/blog/1670990">http://zheyiw.iteye.com/blog/1670990</a>