Android實(shí)現(xiàn)自定義Crash handler記錄崩潰信息實(shí)例代碼
前言
在使用自己開(kāi)發(fā)的android應(yīng)用時(shí),偶爾會(huì)出現(xiàn) 系統(tǒng)已停止運(yùn)行 錯(cuò)誤.這時(shí)候如果能記錄錯(cuò)誤日志,是非常有幫助的。
App異常崩潰信息存入文件中。
應(yīng)用崩潰時(shí),盡可能的收集多的數(shù)據(jù),方便后續(xù)定位追蹤修改。
如果可以,盡量將崩潰日志上傳到服務(wù)器。一些集成服務(wù)已經(jīng)提供了相應(yīng)的功能。
主要使用的方法是Thread.UncaughtExceptionHandler
方法如下
一般在application中啟動(dòng)CrashHandler,個(gè)人認(rèn)為應(yīng)該放在調(diào)用其他模塊前盡早啟動(dòng)。
CrashHandler.java
import android.os.Build;
import android.os.Environment;
import android.os.Process;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class CrashHandler implements Thread.UncaughtExceptionHandler {
private static final String TAG = "CrashHandler";
private static final boolean DEBUG = true;
// 自定義存儲(chǔ)的目錄
private static final String PATH = Environment.getExternalStorageDirectory().getPath() + "/myApp/log/";
private static final String FILE_NAME = "crash";
private static final String FILE_NAME_SUFFIX = ".txt";
private String phoneInfo;
private static CrashHandler instance = new CrashHandler();
private Thread.UncaughtExceptionHandler mDefaultCrashHandler;
private CrashHandler() {
}
public static CrashHandler getInstance() {
return instance;
}
public void init() {
mDefaultCrashHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
phoneInfo = getPhoneInformation();
}
/**
* 這個(gè)是最關(guān)鍵的函數(shù),當(dāng)程序中有未被捕獲的異常,系統(tǒng)將會(huì)自動(dòng)調(diào)用uncaughtException方法
* thread為出現(xiàn)未捕獲異常的線程,ex為未捕獲的異常,有了這個(gè)ex,我們就可以得到異常信息
*/
@Override
public void uncaughtException(Thread thread, Throwable ex) {
try {
//導(dǎo)出異常信息到SD卡中
dumpExceptionToSDCard(ex);
//這里可以上傳異常信息到服務(wù)器,便于開(kāi)發(fā)人員分析日志從而解決bug
uploadExceptionToServer();
} catch (IOException e) {
e.printStackTrace();
}
ex.printStackTrace();
//如果系統(tǒng)提供默認(rèn)的異常處理器,則交給系統(tǒng)去結(jié)束程序,否則就由自己結(jié)束自己
if (mDefaultCrashHandler != null) {
mDefaultCrashHandler.uncaughtException(thread, ex);
} else {
try {
Thread.sleep(2000); // 延遲2秒殺進(jìn)程
} catch (InterruptedException e) {
e.printStackTrace();
}
android.os.Process.killProcess(Process.myPid());
}
}
private void dumpExceptionToSDCard(Throwable ex) throws IOException {
//如果SD卡不存在或無(wú)法使用,則無(wú)法把異常信息寫(xiě)入SD卡
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
if (DEBUG) {
Log.e(TAG, "sdcard unmounted,skip dump exception");
return;
}
}
File dir = new File(PATH);
if (!dir.exists()) {
dir.mkdirs();
}
long current = System.currentTimeMillis();
String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(new Date(current));
File file = new File(PATH + FILE_NAME + time + FILE_NAME_SUFFIX);
try {
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file)));
pw.println(time);
pw.println(phoneInfo);
pw.println();
ex.printStackTrace(pw);
pw.close();
Log.e(TAG, "dump crash info seccess");
} catch (Exception e) {
Log.e(TAG, e.getMessage());
Log.e(TAG, "dump crash info failed");
}
}
private void uploadExceptionToServer() {
// 將異常信息發(fā)送到服務(wù)器
}
private String getPhoneInformation() {
StringBuilder sb = new StringBuilder();
sb.append("App version name:")
.append(BuildConfig.VERSION_NAME)
.append(", version code:")
.append(BuildConfig.VERSION_CODE).append("\n");
//Android版本號(hào)
sb.append("OS Version: ");
sb.append(Build.VERSION.RELEASE);
sb.append("_");
sb.append(Build.VERSION.SDK_INT).append("\n");
//手機(jī)制造商
sb.append("Vendor: ");
sb.append(Build.MANUFACTURER).append("\n");
//手機(jī)型號(hào)
sb.append("Model: ");
sb.append(Build.MODEL).append("\n");
//CPU架構(gòu)
sb.append("CPU ABI:").append("\n");
for (String abi : Build.SUPPORTED_ABIS) {
sb.append(abi).append("\n");
}
return sb.toString();
}
}
使用方式,可在Application中調(diào)用初始化方法
@Override
public void onCreate() {
super.onCreate();
// init application...
CrashHandler.getInstance().init();
}
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
android panellistview 圓角實(shí)現(xiàn)代碼
android panellistview 圓角是每一個(gè)android開(kāi)發(fā)者都具備的一項(xiàng),對(duì)于新手朋友來(lái)說(shuō)可能有點(diǎn)難度,接下來(lái)將詳細(xì)介紹,需要了解的朋友可以參考下2012-12-12
詳解Android的網(wǎng)絡(luò)數(shù)據(jù)存儲(chǔ)
LeanCloud是一種簡(jiǎn)單高效的數(shù)據(jù)和文件存儲(chǔ)服務(wù),本文主要介紹了利用LeanCloud來(lái)進(jìn)行網(wǎng)絡(luò)數(shù)據(jù)的存儲(chǔ)的實(shí)現(xiàn)方法。具有很好的參考價(jià)值,需要的朋友一起來(lái)看下吧2016-12-12
android webview中使用Java調(diào)用JavaScript方法并獲取返回值
這篇文章主要介紹了android webview中使用Java調(diào)用JavaScript方法并獲取返回值,本文直接給出代碼示例,需要的朋友可以參考下2015-03-03
android車(chē)牌識(shí)別系統(tǒng)EasyPR使用詳解
這篇文章主要為大家詳細(xì)介紹了android車(chē)牌識(shí)別系統(tǒng)EasyPR使用,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12
Android編程實(shí)現(xiàn)動(dòng)畫(huà)自動(dòng)播放功能
這篇文章主要介紹了Android編程實(shí)現(xiàn)動(dòng)畫(huà)自動(dòng)播放功能,結(jié)合實(shí)例形式分析了Android動(dòng)畫(huà)自動(dòng)播放功能的實(shí)現(xiàn)方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2017-07-07
Android 開(kāi)發(fā)之dataBinding與ListView及事件
這篇文章主要介紹了Android 開(kāi)發(fā)之dataBinding與ListView及事件的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-10-10
Android實(shí)現(xiàn)淘寶倒計(jì)時(shí)功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)淘寶倒計(jì)時(shí),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-02-02

