本篇文章包含以下內容:
Crash異常捕獲的簡單使用 Crash異常捕獲并發送到服務器
在項目中,我們常常會遇到Crash的現象,也就是程序崩潰的時候,這個時候最常看到的就是這個界面
如果你的項目已經發布到市場上了,這樣的崩潰對于開發人員是看不到的,所以我們得想方法將崩潰信息發送到服務器,交給我們的程序員查看,Google考慮到這一點,也提供了Thread.UncaughtExceptionHandler接口來實現這一問題
一、Crash異常捕獲的簡單使用創建Crash異常捕獲很簡單,主要的步驟有:
創建BaseApplication繼承Application并實現Thread.UncaughtExceptionHandler 通過Thread.setDefaultUncaughtExceptionHandler(this)設置默認的異常捕獲 最后在manifests中注冊創建的BaseApplication
public class BaseApplication extends Application implements Thread.UncaughtExceptionHandler { @Override public void onCreate() { super.onCreate(); //設置異常捕獲 Thread.setDefaultUncaughtExceptionHandler(this); } @Override public void uncaughtException(final Thread thread, final Throwable ex) { //當有異常產生時執行該方法 }}
我們可以在uncaughtException()方法中輸出異常信息,并讓它隔兩秒殺死自己進程,這樣就不會彈出崩潰的彈窗,讓它直接退出程序
/** * 當有異常產生時執行該方法 * @param thread 當前線程 * @param ex 異常信息 */@Overridepublic void uncaughtException(final Thread thread, final Throwable ex) { new Thread(new Runnable() { @Override public void run() { Log.e("TAG","currentThread:"+Thread.currentThread()+"---thread:"+thread.getId()+"---ex:"+ex.toString()); } }).start(); SystemClock.sleep(2000); android.os.Process.killProcess(android.os.Process.myPid());}
最后一步,別忘了在manifests中注冊BaseApplication
我們通過運行這個方法,來測試我們的程序
private void testError() { int a = 10 / 0;}
查看Log信息,驗證我們的錯誤信息
12-18 11:40:02.074 7510-7555/com.handsome.ap E/TAG: currentThread:Thread[Thread-325,5,main]---thread:1---ex:java.lang.RuntimeException: Unable to start activity ComponentInfo{com.handsome.ap/com.handsome.ap.Activity.MainActivity}: java.lang.ArithmeticException: divide by zero
完整代碼
public class BaseApplication extends Application implements Thread.UncaughtExceptionHandler { @Override public void onCreate() { super.onCreate(); //設置異常捕獲 Thread.setDefaultUncaughtExceptionHandler(this); } /** * 當有異常產生時執行該方法 * @param thread 當前線程 * @param ex 異常信息 */ @Override public void uncaughtException(final Thread thread, final Throwable ex) { new Thread(new Runnable() { @Override public void run() { Log.e("TAG","currentThread:"+Thread.currentThread()+"---thread:"+thread.getId()+"---ex:"+ex.toString()); } }).start(); SystemClock.sleep(2000); android.os.Process.killProcess(android.os.Process.myPid()); }}二、Crash異常捕獲并發送到服務器
其實這里就是將上面的簡單使用進行封裝,在一個類中處理相關的邏輯,主要步驟和上面是一樣的
public class CrashHandler implements Thread.UncaughtExceptionHandler { /** * 捕獲異常回掉 * * @param thread 當前線程 * @param ex 異常信息 */ @Override public void uncaughtException(Thread thread, Throwable ex) { //導出異常信息到SD卡 dumpExceptionToSDCard(ex); //上傳異常信息到服務器 uploadExceptionToServer(ex); //延時1秒殺死進程 SystemClock.sleep(2000); Process.killProcess(Process.myPid()); }}
我們為下面的信息保存先提供一些成員變量
//文件夾目錄private static final String PATH = Environment.getExternalStorageDirectory().getPath() + "/crash_log/";//文件名private static final String FILE_NAME = "crash";//文件名后綴private static final String FILE_NAME_SUFFIX = ".trace";//上下文private Context mContext;//單例模式private static CrashHandler sInstance = new CrashHandler();private CrashHandler() {}public static CrashHandler getInstance() { return sInstance;}
提供一個初始化的方法,記得調用Thread.setDefaultUncaughtExceptionHandler(this)這個方法
/** * 初始化方法 * * @param context */public void init(Context context) { //將當前實例設為系統默認的異常處理器 Thread.setDefaultUncaughtExceptionHandler(this); //獲取Context,方便內部使用 mContext = context.getApplicationContext();}
剩下的就是保存異常信息了,這里發送到服務端采用的是Bmob第三方后端云
/** * 導出異常信息到SD卡 * * @param ex */private void dumpExceptionToSDCard(Throwable ex) { if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { 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").format(new Date(current)); //以當前時間創建log文件 File file = new File(PATH + FILE_NAME + time + FILE_NAME_SUFFIX); try { //輸出流操作 PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file))); //導出手機信息和異常信息 PackageManager pm = mContext.getPackageManager(); PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES); pw.println("發生異常時間:" + time); pw.println("應用版本:" + pi.versionName); pw.println("應用版本號:" + pi.versionCode); pw.println("android版本號:" + Build.VERSION.RELEASE); pw.println("android版本號API:" + Build.VERSION.SDK_INT); pw.println("手機制造商:" + Build.MANUFACTURER); pw.println("手機型號:" + Build.MODEL); ex.printStackTrace(pw); //關閉輸出流 pw.close(); } catch (Exception e) { }}/** * 上傳異常信息到服務器 * * @param ex */private void uploadExceptionToServer(Throwable ex) { Error error = new Error(ex.getMessage()); error.save(new SaveListener() { @Override public void done(String objectId, BmobException e) { } });}
在我們的Application中創建該異常捕獲
CrashHandler crashHandler = CrashHandler.getInstance();crashHandler.init(this);
我們同樣按照上面的方法來測試這個異常捕獲,運行程序,在文件夾中找到我們創建的目錄
找到對應文件
查看對應信息
后臺數據庫的信息
完整代碼
public class CrashHandler implements Thread.UncaughtExceptionHandler { //文件夾目錄 private static final String PATH = Environment.getExternalStorageDirectory().getPath() + "/crash_log/"; //文件名 private static final String FILE_NAME = "crash"; //文件名后綴 private static final String FILE_NAME_SUFFIX = ".trace"; //上下文 private Context mContext; //單例模式 private static CrashHandler sInstance = new CrashHandler(); private CrashHandler() {} public static CrashHandler getInstance() { return sInstance; } /** * 初始化方法 * * @param context */ public void init(Context context) { //將當前實例設為系統默認的異常處理器 Thread.setDefaultUncaughtExceptionHandler(this); //獲取Context,方便內部使用 mContext = context.getApplicationContext(); } /** * 捕獲異常回掉 * * @param thread 當前線程 * @param ex 異常信息 */ @Override public void uncaughtException(Thread thread, Throwable ex) { //導出異常信息到SD卡 dumpExceptionToSDCard(ex); //上傳異常信息到服務器 uploadExceptionToServer(ex); //延時1秒殺死進程 SystemClock.sleep(2000); Process.killProcess(Process.myPid()); } /** * 導出異常信息到SD卡 * * @param ex */ private void dumpExceptionToSDCard(Throwable ex) { if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { 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").format(new Date(current)); //以當前時間創建log文件 File file = new File(PATH + FILE_NAME + time + FILE_NAME_SUFFIX); try { //輸出流操作 PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file))); //導出手機信息和異常信息 PackageManager pm = mContext.getPackageManager(); PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES); pw.println("發生異常時間:" + time); pw.println("應用版本:" + pi.versionName); pw.println("應用版本號:" + pi.versionCode); pw.println("android版本號:" + Build.VERSION.RELEASE); pw.println("android版本號API:" + Build.VERSION.SDK_INT); pw.println("手機制造商:" + Build.MANUFACTURER); pw.println("手機型號:" + Build.MODEL); ex.printStackTrace(pw); //關閉輸出流 pw.close(); } catch (Exception e) { } } /** * 上傳異常信息到服務器 * * @param ex */ private void uploadExceptionToServer(Throwable ex) { Error error = new Error(ex.getMessage()); error.save(new SaveListener() { @Override public void done(String objectId, BmobException e) { } }); }}
到這里我們的Crash異常捕獲就結束了,很簡單的一段代碼就可以解決你缺少的項目經驗
看文倉www.kanwencang.com網友整理上傳,為您提供最全的知識大全,期待您的分享,轉載請注明出處。
歡迎轉載:http://www.kanwencang.com/bangong/20170114/87911.html
文章列表