定义CrashLog文件:如果有存储器,则将文件保存在存储器下。否则保存在data目录下。存储器不一定是SD卡,也可能是mount出来的一块存储空间(不是内存)。比如,小米3就没有SD卡。
public class CrashLog { private static Context mContext; public static final String DIR_FOR_APP = "myApp"; public static final String FILE_NAME_FOR_CRASH__LOG = "crash.txt"; public static void setContext( Context aContext ) { mContext = aContext.getApplicationContext(); } public static void writeLog(String log) throws Exception { File dir = createFileDir(DIR_FOR_APP); File file = new File(dir.getPath(), FILE_NAME_FOR_CRASH__LOG); if(!file.exists()){ file.createNewFile(); } StringBuffer orgStr = new StringBuffer(); FileReader fr = new FileReader(file); int ch = 0; while((ch = fr.read()) != -1) { orgStr.append((char)ch); } fr.close(); Calendar c = Calendar.getInstance(); String time = String.format("%2d:", c.get(Calendar.HOUR))+ String.format("%2d:", c.get(Calendar.MINUTE))+ String.format("%2d", c.get(Calendar.SECOND))+" "; String str = orgStr.toString() + "\r\n" + time + log + "\r\n"; FileWriter fw = new FileWriter(file); fw.write(str); fw.close(); } public static void clearLog(){ String dirPath = getDirPath(DIR_FOR_APP); if( dirPath != null ) { File file = new File(FILE_NAME_FOR_CRASH__LOG); if(file.exists()){ file.delete(); } } } public static String getDirPath(String dirName){ String filePath = null; String state = Environment.getExternalStorageState(); if (state.equals(Environment.MEDIA_MOUNTED)) { // 如果有存储器,则返回存储器的路径 filePath = Environment.getExternalStorageDirectory() + File.separator + dirName; } else {// 否则返回data目录的路径 filePath = mContext.getCacheDir().getPath() + File.separator + dirName; } return filePath; } public static File createFileDir(String dirName) { String filePath = getDirPath(dirName); if( filePath == null ) { return null; } File destDir = new File(filePath); if (!destDir.exists()) { destDir.mkdirs(); } return destDir; } }
2. 定义CrashHandler异常捕获类:当程序抛出异常后,由CrashHandler先捕获。将异常堆栈信息和手机系统信息打印到手机制定位置的log文件后,退出。
public class CrashHandler implements UncaughtExceptionHandler {
private Context mContext;
private static CrashHandler mInstance = null;
// 系统默认的异常处理(默认情况下,系统会终止当前的异常程序)
private UncaughtExceptionHandler mDefaultCrashHandler;
private CrashHandler(Context c) {
// 获取系统默认的异常处理器
mDefaultCrashHandler = Thread
.getDefaultUncaughtExceptionHandler();
// 将当前实例设为系统默认的异常处理器
Thread.setDefaultUncaughtExceptionHandler(this);
// 获取Context,方便内部使用
mContext = c.getApplicationContext();
}
public synchronized static CrashHandler create(Context cxt) {
if (mInstance == null) {
mInstance = new CrashHandler(cxt);
}
return mInstance;
}
/**
* 当UncaughtException发生时会回调该函数来处理
*/
@Override
public void uncaughtException(Thread thread, Throwable ex) {
// TODO Auto-generated method stub
StringBuffer logInfo = new StringBuffer();
logInfo.append("Exception: ");
logInfo.append(ex.getMessage());
logInfo.append("\r\n");
logInfo.append(getStackMsg(ex));
logInfo.append("Phone informations:");
logInfo.append("\r\n");
try {
logInfo.append(getPhoneInfo());
// 导出异常信息到存储器中
CrashLog.writeLog(logInfo.toString());
} catch (Exception e) {
//忽略异常
} finally {
// 如果系统提供了默认的异常处理器,则交给系统去结束程序,
if (mDefaultCrashHandler != null) {
mDefaultCrashHandler.uncaughtException(thread, ex);
} else {
MyApplication.getInstance().exit();
}
}
}
private static String getStackMsg(Throwable e) {
StringBuffer sb = new StringBuffer();
StackTraceElement[] stackArray = e.getStackTrace();
for (int i = 0; i < stackArray.length; i++) {
StackTraceElement element = stackArray[i];
sb.append(element.toString() + "\r\n");
}
return sb.toString();
}
private String getPhoneInfo()
throws NameNotFoundException {
StringBuffer info = new StringBuffer();
// 应用的版本号
PackageManager pm = mContext.getPackageManager();
PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(),
PackageManager.GET_ACTIVITIES);
info.append("App Version Name: ");
info.append(pi.versionName);
info.append("\r\n");
// android版本号
info.append("OS Version: ");
info.append(Build.VERSION.RELEASE);
info.append("_");
info.append(Build.VERSION.SDK_INT);
info.append("\r\n");
// 手机制造商
info.append("Vendor: ");
info.append(Build.MANUFACTURER);
info.append("\r\n");
// 手机型号
info.append("Model: ");
info.append(Build.MODEL);
info.append("\r\n");
// cpu架构
info.append("CPU ABI: ");
info.append(Build.CPU_ABI);
info.append("\r\n");
return info.toString();
}
}
3. 自定义Application类,初始化CrashLog和CrashHandler,并提供完全退出应用的接口exit()。
public class MyApplication extends Application{
// 单例模式
private static MyApplication mAppInstance;
// Activity容器
private List<Activity> mActivityList = new LinkedList<Activity>();
public MyApplication(){
}
public static MyApplication getInstance() {
if( mAppInstance == null ) {
mAppInstance = new MyApplication();
}
return mAppInstance;
}
// 每新建一个Activity,都要添加到容器中
public void addActivity(Activity a){
mActivityList.add(a);
}
// 遍历容器中所有Activity并finish
public void exit(){
for (Activity activity : mActivityList) {
activity.finish();
}
System.exit(0);
}
@Override
public void onCreate() {
super.onCreate();
CrashLog.setContext(this);
CrashHandler.create(this);
}
}