package com.chinaztt.fda.crash;
import android.content.Context;
import android.os.Environment;
import android.os.Looper;
import android.widget.Toast;
import com.chinaztt.fda.utils.IoUtils;
import com.chinaztt.fda.utils.Log;
import com.chinaztt.fda.utils.ManagerActivity;
import com.chinaztt.fda.utils.StrUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.TimeZone;
/**
* 当前类注释:客户端运行 异常崩溃数据扑捉异常保存SD卡或者实时投递服务器工具类
* 项目名:FastDev4Android
* 包名:com.chinaztt.fda.crash
* 作者:江清清 on 15/10/26 13:29
* 邮箱:jiangqqlmj@163.com
* QQ: 781931404
* 公司:江苏中天科技软件技术有限公司
*/
public class CustomCrash implements Thread.UncaughtExceptionHandler{
private static final String TAG="CustomCrash";
private static final int TYPE_SAVE_SDCARD=1; //崩溃日志保存本地SDCard --建议开发模式使用
private static final int TYPE_SAVE_REMOTE=2; //崩溃日志保存远端服务器 --建议生产模式使用
private int type_save=2; //崩溃保存日志模式 默认为2,采用保存Web服务器
private static final String CRASH_SAVE_SDPATH="sdcard/fda_cache/"; //崩溃日志SD卡保存路径
private static final String CARSH_LOG_DELIVER="http://img2.xxh.cc:8080/SalesWebTest/CrashDeliver";
private static CustomCrash instance = new CustomCrash();
private Context mContext;
private CustomCrash() {
}
/**
*
* @return
*/
public static CustomCrash getInstance() {
return instance;
}
/*
* (non-Javadoc) 进行重写捕捉异常
*
* @see
* java.lang.Thread.UncaughtExceptionHandler#uncaughtException(java.lang
* .Thread, java.lang.Throwable)
*/
@Override
public void uncaughtException(Thread thread, Throwable ex) {
if(type_save==TYPE_SAVE_SDCARD){
// 1,保存信息到sdcard中
saveToSdcard(mContext, ex);
}else if(type_save==TYPE_SAVE_REMOTE){
// 2,异常崩溃信息投递到服务器
saveToServer(mContext,ex);
}
// 3,应用准备退出
showToast(mContext, "很抱歉,程序发生异常,即将推出.");
try {
Thread.sleep(3500);
} catch (InterruptedException e) {
e.printStackTrace();
}
ManagerActivity.getInstance().finishActivity();
android.os.Process.killProcess(android.os.Process.myPid());
}
/**
* 设置自定异常处理类
*
* @param pContext
*/
public void setCustomCrashInfo(Context pContext) {
this.mContext = pContext;
Thread.setDefaultUncaughtExceptionHandler(this);
}
/**
* 保存异常信息到sdcard中
*
* @param pContext
* @param ex
* 异常信息对象
*/
private void saveToSdcard(Context pContext, Throwable ex) {
String fileName = null;
StringBuffer sBuffer = new StringBuffer();
// 添加异常信息
sBuffer.append(getExceptionInfo(ex));
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
File file1 = new File(CRASH_SAVE_SDPATH);
if (!file1.exists()) {
file1.mkdir();
}
fileName = file1.toString() + File.separator + paserTime(System.currentTimeMillis()) + ".log";
File file2 = new File(fileName);
FileOutputStream fos;
try {
fos = new FileOutputStream(file2);
fos.write(sBuffer.toString().getBytes());
fos.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 进行把数据投递至服务器
* @param pContext
* @param ex 崩溃异常
*/
private void saveToServer(Context pContext,Throwable ex){
final String carsh_log=getExceptionInfo(ex);
new Thread(new Runnable() {
@Override
public void run() {
HashMap<String,String> params=new HashMap<String,String>();
params.put("crash_log",carsh_log);
String result= IoUtils.responseFromServiceByGetNo(CARSH_LOG_DELIVER, params);
if (result.equals("1")){
Log.d(TAG,"崩溃日志投递成功...");
}else {
Log.d(TAG,"崩溃日志投递失败...");
}
}
}).start();
}
/**
* 获取并且转化异常信息
* 同时可以进行投递相关的设备,用户信息
* @param ex
* @return 异常信息的字符串形式
*/
private String getExceptionInfo(Throwable ex) {
StringWriter sw = new StringWriter();
ex.printStackTrace(new PrintWriter(sw));
StringBuffer stringBuffer=new StringBuffer();
stringBuffer.append("---------Crash Log Begin---------\n");
//在这边可以进行相关设备信息投递--这边就稍微设置几个吧
//其他设备和用户信息大家可以自己去扩展收集上传投递
stringBuffer.append("SystemVersion:"+ StrUtils.getLocalSystemVersion()+"\n");
stringBuffer.append(sw.toString()+"\n");
stringBuffer.append("---------Crash Log End---------\n");
return stringBuffer.toString();
}
/**
* 进行弹出框提示
*
* @param pContext
* @param msg
*/
private void showToast(final Context pContext, final String msg) {
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
Toast.makeText(pContext, msg, Toast.LENGTH_SHORT).show();
Looper.loop();
}
}).start();
}
/**
* 将毫秒数转换成yyyy-MM-dd-HH-mm-ss的格式
* @param milliseconds
* @return
*/
private String paserTime(long milliseconds) {
System.setProperty("user.timezone", "Asia/Shanghai");
TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");
TimeZone.setDefault(tz);
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
String times = format.format(new Date(milliseconds));
return times;
}
}