您的位置:首页 > 移动开发 > Android开发

Android应用如何反馈Crash报告

2014-12-09 11:07 393 查看
/article/4892826.html

一、为什么要Crash

crash可以理解成堕落,垮台。按照我们通俗理解就是android App 因为不可预知的因素导致奔溃。

即使我们的程序发布前,经历了很多的测试,但是经过无数用户各种使用情况之后,可能会发生意想不到的crash.

为了及时反馈bug,通常我们都需要一个crash机制,以让开发人员尽快了解到问题所在,在下个版本中及时改进。

二、如何做到Crash

java的Thread中有一个UncaughtExceptionHandler接口,该接口的作用主要是为了
Thread 因未捕获的异常而突然终止时,调用处理程序。

接口下面有setDefaultUncaughtExceptionHandler
(
Thread.UncaughtExceptionHandler
eh)


方法,方法主要作用为设置当线程由于未捕获到异常而突然终止,并且没有为该线程定义其他处理程序时所调用的默认处理程序。

通用demo如下

public class DefaultExceptionHandler implements UncaughtExceptionHandler {

private Context act = null;

public DefaultExceptionHandler(Context act) {

this.act = act;

}

@Override

public void uncaughtException(Thread thread, Throwable ex) {

// 收集异常信息 并且发送到服务器

sendCrashReport(ex);

// 等待半秒

try {

Thread.sleep(500);

} catch (InterruptedException e) {

//

}

// 处理异常

handleException();

}

private void sendCrashReport(Throwable ex) {

StringBuffer exceptionStr = new StringBuffer();

exceptionStr.append(ex.getMessage());

StackTraceElement[] elements = ex.getStackTrace();

for (int i = 0; i < elements.length; i++) {

exceptionStr.append(elements[i].toString());

}

//TODO

//发送收集到的Crash信息到服务器

}

private void handleException() {

//TODO

//这里可以对异常进行处理。

//比如提示用户程序崩溃了。

//比如记录重要的信息,尝试恢复现场。

//或者干脆记录重要的信息后,直接杀死程序。

}

}

在主线程中调用

Thread.setDefaultUncaughtExceptionHandler(new DefaultExceptionHandler(

this.getApplicationContext()));

之前一直对公司项目的CrashHandler类不是很熟悉,这里结合项目代码,看下是如何具体实现的

首先,在AndroidManifest.xml中的application节点中配置name

<application
android:name="com.newland.mbop.application.CrashHandlerApp">

CrashHandlerApp中初始化CrashHandler(实现UncaughtExceptionHandler的实现类)

@Override
public void onCreate() {
CrashHandler ch = CrashHandler.getInstance();
ch.init(this);

super.onCreate();
}

最后看下CrashHandler类的具体实现

public class CrashHandler implements UncaughtExceptionHandler {

/** 获取CrashHandler实例 */
public static CrashHandler getInstance() {
if (INSTANCE == null)
INSTANCE = new CrashHandler();
return INSTANCE;
}
public void init(CrashHandlerApp app) {
Log.i("BaseActivity","init()");
this.app = app;
// 设置该类为线程默认UncatchException的处理器。
Thread.setDefaultUncaughtExceptionHandler(this);
}

/**
* 当UncaughtException发生时会回调该函数来处理
*/
@Override
public void uncaughtException(Thread thread, Throwable ex) {
System.out.println("system wrong....");
// MBOPApplication app=(MBOPApplication) mainContext;
// app.setNeed2Exit(true);
//异常信息收集
collectCrashExceptionInfo(thread, ex);
//应用程序信息收集
collectCrashApplicationInfo(app);
//保存错误报告文件到文件。
saveCrashInfoToFile(ex);
//MBOPApplication.setCrash(true);
//判断是否为UI线程异常,thread.getId()==1 为UI线程
if (thread.getId() != 1) {
//            System.out.println("Exception ThreadId" + thread.getId());
thread.interrupt();
//TODO 跳转到IndexActivity
System.out.println("Thread ID--->" + Thread.currentThread().getId());
//            Intent intent =new Intent(mainContext,IndexActivity.class);
//            actContext.startActivity(intent);
//弹出对话框提示用户是否上传异常日志至服务器
new Thread(){
public void run() {}{
Looper.prepare();
new AlertDialog.Builder(app.getCurrentAct()).setTitle("异常处理").setMessage("您的程序出现异常,是否将异常信息上传至服务器?")
.setPositiveButton("是", new OnClickListener() {

public void onClick(DialogInterface dialog, int which) {
new Thread(new Runnable() {

@Override
public void run() {
sendCrashReportsToServer(app,false);

}
}).start();
//                            new Thread(){
//                                public void run() {}{
//                                    try{
//                                        System.out.println("执行上传线程ID"+this.getId());
//                                        this.sleep(5000);
//                                    }catch(Exception e){
//
//                                    }
//                                    sendCrashReportsToServer(app);
//                                }
//                            }.start();
}
}).setNegativeButton("否", new OnClickListener() {

@Override
public void onClick(DialogInterface dialog, int which) {

}
}).create().show();
Looper.loop();
}
}.start();

} else {

//            UserSessionCache usc=UserSessionCache.getInstance();
//            ObjectOutputStream oos=null;
//            try {
//                oos.writeObject(usc);
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//            SharedPreferences prefenPreferences = mainContext
//            .getSharedPreferences("IsMBOPCrash",Activity.MODE_PRIVATE);
//            SharedPreferences.Editor editor = prefenPreferences.edit();
//            editor.clear();
//            editor.putBoolean("ISCRASH", true);
//            editor.commit();

// 方案一:将所有Activity放入Activity列表中,然后循环从列表中删除,即可退出程序

for (int i = app.getActivityList().size()-1; i >=0; i--) {
Activity act = app.getActivityList().get(i);
act.finish();
}
CoreCommonMethod.setCrash(app, true);
Intent intent = new Intent(app, WelcomeActivity.class);
intent.putExtra(WelcomeActivity.EXTRA_DIRECT_TO_INDEX, true);
intent.putExtra(WelcomeActivity.EXTRA_USERINFO, UserSessionCache.getInstance().getUserInfo());
intent.putExtra(WelcomeActivity.EXTRA_CURRENT_PORTAL_ID, UserSessionCache.getInstance().getCurrentPortalId());
//            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//            app.startActivity(intent);
android.os.Process.killProcess(android.os.Process.myPid());

//方案二:直接使用ActivityManager的restartPackage方法关闭应用程序,
//此方法在android2.1之后被弃用,不起作用
//            ActivityManager am = (ActivityManager) mainContext.getSystemService(Context.ACTIVITY_SERVICE);
//            am.restartPackage(mainContext.getPackageName());

}
}

}

一般来说,发生crash的时候,我们需要知道客户端的SDK版本,程序版本,分辨率等等因素
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: