標籤:android 異常
捕捉運行時異常
APP軟體在運行時,難免會出現運行時異常,而導致程式crash。當然,如果在debug模式下開發的時候,是可以通過查看logcat日誌來查看異常訊息,從而進行處理。但是,如果我們在發布版本之後,使用者在使用的時候crash掉了,就無法查看異常資訊,也就很難找出bug來解決問題。
還好在java線程類中,有一個針對上述問題的解決辦法:線上程中捕捉未處理的異常。因為crash時,拋出的異常就是因為沒有在app中catch處理,就會拋給系統,如果我們在這個時候對這個能夠對這個異常進行處理,就最好不過了,這樣就能列印異常資訊,就能發布給伺服器,供開發人員查看。
一,寫一個CrashHanler類
package com.raise.wind.utils;import android.os.Environment;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;/** * Created by yu on 2015/7/15. */public class CrashHandler implements Thread.UncaughtExceptionHandler { public static CrashHandler instance; private CrashHandler() { } public static CrashHandler get_instance() { if (instance == null) new CrashHandler(); return instance; } public void init() { Thread.setDefaultUncaughtExceptionHandler(this); } @Override public void uncaughtException(Thread thread, Throwable ex) { saveFile(ex.getMessage(), "crash.txt"); //退出程式 //這裡由於是我們自己處理的異常,必須手動退出程式,不然系統出一隻處於crash等待狀態 android.os.Process.killProcess(android.os.Process.myPid()); System.exit(1); } public static void saveFile(String data, String file_name) { File sdPath = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "aacrash" + File.separator + "cache"); if (!sdPath.exists()) { sdPath.mkdirs(); } File file = new File(sdPath, file_name); FileOutputStream fos = null; try { fos = new FileOutputStream(file); fos.write(data.getBytes("UTF-8")); } catch (Exception e) { e.printStackTrace(); } finally { if (fos != null) try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } }}
二,在Application中聲明
記得在Androidanifest.xml中配置
package com.raise.wind.app;import android.app.Application;import com.raise.wind.utils.CrashHandler;/** * Created by yu on 2015/7/15. */public class APP extends Application { @Override public void onCreate() { super.onCreate(); CrashHandler.get_instance().init(); }}
三,測試
這樣就聲明了我們線程中出現的為捕捉異常交給CrashHandler類來處理。
現在我們寫一個null 指標異常來測試:
package com.raise.wind.crashproject;import android.os.Bundle;import android.support.v7.app.ActionBarActivity;import android.widget.TextView;public class MainActivity extends ActionBarActivity { TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView.setText("text"); }}
開啟app,發現程式立即crash,開啟檔案管理能找到在程式中儲存的檔案,裡面有異常訊息
Unable to start activity ComponentInfo{com.raise.wind.crashproject/com.raise.wind.crashproject.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method ‘void android.widget.TextView.setText(java.lang.CharSequence)‘ on a null object reference
當然,這隻是異常訊息的開頭的提示,如果要想全部列印出來,使用下面代碼:
Could not execute method of the activityandroid.view.View$1.onClick(View.java:4010)android.view.View.performClick(View.java:4759)android.view.View$PerformClick.run(View.java:19770)android.os.Handler.handleCallback(Handler.java:739)android.os.Handler.dispatchMessage(Handler.java:95)android.os.Looper.loop(Looper.java:135)android.app.ActivityThread.main(ActivityThread.java:5235)java.lang.reflect.Method.invoke(Native Method)java.lang.reflect.Method.invoke(Method.java:372)com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:906)com.android.internal.os.ZygoteInit.main(ZygoteInit.java:701)Caused by nulljava.lang.reflect.Method.invoke(Native Method)java.lang.reflect.Method.invoke(Method.java:372)android.view.View$1.onClick(View.java:4005)android.view.View.performClick(View.java:4759)android.view.View$PerformClick.run(View.java:19770)android.os.Handler.handleCallback(Handler.java:739)android.os.Handler.dispatchMessage(Handler.java:95)android.os.Looper.loop(Looper.java:135)android.app.ActivityThread.main(ActivityThread.java:5235)java.lang.reflect.Method.invoke(Native Method)java.lang.reflect.Method.invoke(Method.java:372)com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:906)com.android.internal.os.ZygoteInit.main(ZygoteInit.java:701)Caused by Attempt to invoke virtual method ‘void android.widget.TextView.setText(java.lang.CharSequence)‘ on a null object referencecom.raise.wind.crashproject.MainActivity.click_1(MainActivity.java:21)java.lang.reflect.Method.invoke(Native Method)java.lang.reflect.Method.invoke(Method.java:372)android.view.View$1.onClick(View.java:4005)android.view.View.performClick(View.java:4759)android.view.View$PerformClick.run(View.java:19770)android.os.Handler.handleCallback(Handler.java:739)android.os.Handler.dispatchMessage(Handler.java:95)android.os.Looper.loop(Looper.java:135)android.app.ActivityThread.main(ActivityThread.java:5235)java.lang.reflect.Method.invoke(Native Method)java.lang.reflect.Method.invoke(Method.java:372)com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:906)com.android.internal.os.ZygoteInit.main(ZygoteInit.java:701)
這個類一般結合log4j來記錄日誌,並且在發生crash時,將log檔案發送到伺服器。
這樣程式就可以查看使用者手機端的crash訊息了,方便我們處理在debug模式開發時未發現的異常。
點我下載源碼
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
Android_APP層級的異常處理