import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.os.Environment;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
@SuppressLint("SimpleDateFormat")
public class XTCrash implements UncaughtExceptionHandler
{
private static final String TAG = "CrashHandler";
private Context mContext;// 程序的Context对象
private static XTCrash INSTANCE = new XTCrash();// CrashHandler实例
private Thread.UncaughtExceptionHandler mDefaultHandler;// 系统默认的UncaughtException处理类
private Map<String, String> info = new HashMap<String, String>();// 用来存储设备信息和异常信息
private SimpleDateFormat format = new SimpleDateFormat(
"yyyy-MM-dd-HH-mm-ss");// 用于格式化日期,作为日志文件名的一部分
/** 保证只有一个CrashHandler实例 */
private XTCrash()
{
}
/** 获取CrashHandler实例 ,单例模式 */
public static XTCrash getInstance()
{
return INSTANCE;
}
/**
* 初始化
*
* @param context
*/
public void init(Context context)
{
mContext = context;
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();// 获取系统默认的UncaughtException处理器
Thread.setDefaultUncaughtExceptionHandler(this);// 设置该CrashHandler为程序的默认处理器
}
/**
* 当UncaughtException发生时会转入该重写的方法来处理
*/
@Override
public void uncaughtException(Thread thread, Throwable ex)
{
if (!handleException(ex) && mDefaultHandler != null)
{
// 如果自定义的没有处理则让系统默认的异常处理器来处理
mDefaultHandler.uncaughtException(thread, ex);
}
else
{
try
{
Thread.sleep(3000);// 如果处理了,让程序继续运行3秒再退出,保证文件保存并上传到服务器
}
catch (InterruptedException e)
{
e.printStackTrace();
}
// 退出程序
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
}
}
/**
* 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
*
* @param ex
* 异常信息
* @return true 如果处理了该异常信息;否则返回false.
*/
public boolean handleException(Throwable ex)
{
if (ex == null)
return false;
new Thread()
{
public void run()
{
Looper.prepare();
Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出", Toast.LENGTH_SHORT)
.show();
Looper.loop();
}
}.start();
// 收集设备参数信息
// collectDeviceInfo(mContext);
// 保存日志文件
saveCrashInfo2File(ex);
return true;
}
/**
* 收集设备参数信息
*
* @param context
*/
public void collectDeviceInfo(Context context)
{
try
{
PackageManager pm = context.getPackageManager();// 获得包管理器
PackageInfo pi = pm.getPackageInfo(context.getPackageName(),
PackageManager.GET_ACTIVITIES);// 得到该应用的信息,即主Activity
if (pi != null)
{
String versionName = pi.versionName == null ? "null"
: pi.versionName;
String versionCode = pi.versionCode + "";
info.put("versionName", versionName);
info.put("versionCode", versionCode);
}
}
catch (NameNotFoundException e)
{
e.printStackTrace();
}
Field[] fields = Build.class.getDeclaredFields();// 反射机制
for (Field field : fields)
{
try
{
field.setAccessible(true);
info.put(field.getName(), field.get("").toString());
Log.d(TAG, field.getName() + ":" + field.get(""));
}
catch (IllegalArgumentException e)
{
e.printStackTrace();
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
}
}
/**
* 保存异常信息
*
* @param ex
* @return
*/
private String saveCrashInfo2File(Throwable ex)
{
Writer writer = new StringWriter();
PrintWriter pw = new PrintWriter(writer);
ex.printStackTrace(pw);
Throwable cause = ex.getCause();
// 循环着把所有的异常信息写入writer中
while (cause != null)
{
cause.printStackTrace(pw);
cause = cause.getCause();
}
pw.close();// 记得关闭
String result = writer.toString();
Log.e("exception:", result);
long timetamp = System.currentTimeMillis();
String time = format.format(new Date());
String prefix = "\n" + time + "-" + timetamp + ":\n";
StringBuffer sb = new StringBuffer();
sb.append(prefix);
sb.append(result);
// 保存文件
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED))
{
try
{
File dir = new File( Environment .getExternalStorageDirectory().getAbsolutePath() + "/crash);
Log.i("CrashHandler", dir.toString());
if (!dir.exists())
dir.mkdirs();
FileOutputStream fos = new FileOutputStream(new File(dir,
"exception.log"), true);
fos.write(sb.toString().getBytes());
fos.close();
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
return null;
}
}
XTCrash.getInstance().init(this);Android捕获异常,生成文件
最新推荐文章于 2024-04-30 06:25:15 发布
本文介绍了一种自定义CrashHandler的实现方法,通过继承UncaughtExceptionHandler接口,实现了程序崩溃时的异常捕获和处理流程。该实现包括收集设备信息、保存异常日志文件等功能。
1247

被折叠的 条评论
为什么被折叠?



