一、原理
UncaughtExceptionHandler(未捕获异常处理器)是Thread类的静态内部接口,用来处理用户没有try…caught的异常。也就是系统运行出错throw出来的异常。
setDefaultUncaughtExceptionHandler()是Thread的静态方法。
内部实现:
private static UncaughtExceptionHandler defaultUncaughtHandler;
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler handler) {
Thread.defaultUncaughtHandler = handler;
} 使用方法:Thread.setDefaultUncaughtExceptionHandler(this);二、安卓中的使用
/**
* Created by wangxiaowu on 2018/5/8 14:43
* decribe
*/
public class CrashHandler implements Thread.UncaughtExceptionHandler {
//log保存路径
public static String LOG_PATH;
private Context mContext;
//CrashCatchHandler单例
private static CrashHandler INSTANCE = new CrashHandler ( );
//存储设备信息和异常信息
private Map< String, String > mInfoMap;
private SimpleDateFormat mDateFormat;
private CrashHandler ( ) {
mInfoMap = new LinkedHashMap<>( );
mDateFormat = new SimpleDateFormat ( "yyyy-MM-dd-HH-mm-ss" );
}
/**
* 获取CrashCatchHandler实例 ,单例模式
*/
public static CrashHandler getInstance ( ) { return INSTANCE; }
/**
* 初始化
*
* @param context
*/
public void init ( Context context ) {
mContext = context;
//设置该CrashCatchHandler为程序的默认未捕获异常处理器
Thread.setDefaultUncaughtExceptionHandler ( this );
//如果外存卡可以读写,放在外部存储器,否则放在内部存储器上
if ( Environment.getExternalStorageState ( ).equals ( Environment.MEDIA_MOUNTED ) ) {
// LOG_PATH = mContext.getExternalFilesDir ( "log" ).getPath ( );
LOG_PATH = Environment
.getExternalStorageDirectory() + File.separator+"log"+File.separator;
} else {
LOG_PATH = mContext.getFilesDir ( ).getPath ( );
}
}
/**
* 当UncaughtException发生时会转入该函数来处理
*/
@Override
public void uncaughtException ( Thread thread, Throwable ex ) {
//收集设备参数信息
collectDeviceInfo ( mContext );
//保存日志文件至本地
saveCrashLog (ex);
}
/**
* 收集奔溃设备参数信息
*/
public void collectDeviceInfo ( Context context ) {
try {
PackageManager pm = context.getPackageManager ( );
PackageInfo packageInfo = pm.getPackageInfo ( context.getPackageName ( ), PackageManager.GET_ACTIVITIES );
if ( packageInfo != null ) {
String appName = packageInfo.applicationInfo.packageName;
String versionName = packageInfo.versionName + "";
String versionCode = packageInfo.versionCode + "";
mInfoMap.put ( "包名", appName );
mInfoMap.put ( "版本名", versionName );
mInfoMap.put ( "版本号", versionCode );
}
} catch ( PackageManager.NameNotFoundException e ) {
}
Field[] fields = Build.class.getDeclaredFields ( );
for ( Field field : fields ) {
try {
field.setAccessible ( true );
mInfoMap.put ( field.getName ( ), field.get ( null ).toString ( ) );
} catch ( Exception e ) {
}
}
}
/**
* 保存错误信息到文件中
*
* @param ex
* @return 返回文件名称
*/
private String saveCrashLog ( Throwable ex ) {
StringBuilder stringBuilder = new StringBuilder ( );
for ( Map.Entry< String, String > entry : mInfoMap.entrySet ( ) ) {
String key = entry.getKey ( );
String value = entry.getValue ( );
stringBuilder.append ( key + " = " + value + "\n" );
}
//异常写入stringBuilder
Writer writer = new StringWriter( );
PrintWriter printWriter = new PrintWriter ( writer );
ex.printStackTrace ( printWriter );
//异常原因写入stringBuilder
Throwable cause = ex.getCause ( );
if ( cause != null ) {
cause.printStackTrace ( printWriter );
}
printWriter.close ( );
String result = writer.toString ( );
stringBuilder.append ( result );
try {
String time = mDateFormat.format ( new Date( System.currentTimeMillis ( ) ) );
String fileName = time + ".txt";
File dir = new File ( LOG_PATH );
if ( ! dir.exists ( ) ) {
dir.mkdirs ( );
}
FileOutputStream fos = new FileOutputStream ( dir.getAbsolutePath ( ) + File.separator + fileName );
fos.write ( stringBuilder.toString ( ).getBytes ( ) );
fos.close ( );
return fileName;
} catch ( Exception e ) {
}
return null;
}
}在Application中去调用自定义的UncaughtExceptionHandler。
public class BaseApplication extends Application {
@Override
public void onCreate ( ) {
super.onCreate ( );
CrashHandler.getInstance().init(getApplicationContext ());
}
}
本文介绍如何在安卓应用中使用UncaughtExceptionHandler来捕获并记录未处理的异常,通过单例模式实现CrashHandler,确保应用崩溃时能收集设备信息及异常详情,并将这些信息保存到本地日志文件。
424

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



