有时候由于测试不充分或者程序潜在的问题而导致程序异常崩溃,这个是令人无法接受的,在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>