android全局异常检测并处理

来源:互联网 发布:刷搜狗手机点击优化 编辑:程序博客网 时间:2024/06/12 01:07

作为一名android开发人员,开发好的应用推广出去的话,很难预料到会有哪些异常。

而那些未被捕获的异常如果经常出现的话,会很影响用户体验效果的。

android其实对于这些未知的异常,有一个捕获机制的。

好了,废话不多上,上一个例子。

首先是一个异常处理类:

public class ExceptionHandler implements UncaughtExceptionHandler {/** Debug Log tag */public static final String TAG = "CrashHandler";/** * 是否开启日志输出,在Debug状态下开启, 在Release状态下关闭以提示程序性能 * */public static final boolean DEBUG = true;/** 系统默认的UncaughtException处理类 */private Thread.UncaughtExceptionHandler mDefaultHandler;/** CrashHandler实例 */private static ExceptionHandler instance;/** 程序的Context对象 */private Context mContext;/** 使用Properties来保存设备的信息和错误堆栈信息 */private Properties mDeviceCrashInfo = new Properties();private static final String VERSION_NAME = "versionName";private static final String VERSION_CODE = "versionCode";private static final String OS_VER= "osVer";//安卓版本private static final String Device_TYPE = "deviceType";//手机型号private static final String STACK_TRACE = "STACK_TRACE";/** 错误报告文件的扩展名 */private static final String CRASH_REPORTER_EXTENSION = ".cr";/** 保证只有一个CrashHandler实例 */private ExceptionHandler() {}/** 获取CrashHandler实例 ,单例模式 */public static ExceptionHandler getInstance() {if (instance == null) {instance = new ExceptionHandler();}return instance;}/** * 初始化,注册Context对象, 获取系统默认的UncaughtException处理器, 设置该CrashHandler为程序的默认处理器 * @param ctx */public void init(Context ctx) {mContext = ctx;mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();Thread.setDefaultUncaughtExceptionHandler(this);}/** * 当UncaughtException发生时会转入该函数来处理 */boolean flag=true;@Overridepublic void uncaughtException(Thread thread, Throwable ex) {if(flag==false)return;flag=false;if (!handleException(ex) && mDefaultHandler != null) {// 如果用户没有处理则让系统默认的异常处理器来处理Log.e("TEST", "handle Throwable");} else {// Sleep一会后结束程序Log.e("TEST", "sleep and finish");try {Thread.sleep(3000);} catch (InterruptedException e) {Log.e(TAG, "Error : ", e);}Log.e("TEST", "异常");}//mDefaultHandler.uncaughtException(thread, ex);SPZApplication.getInstance().exit();}/** * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成. 开发者可以根据自己的情况来自定义异常处理逻辑 * @param ex * @return true:如果处理了该异常信息;否则返回false */private boolean handleException(Throwable ex) {if (ex == null) {return true;}final String msg = ex.getLocalizedMessage();// 使用Toast来显示异常信息new Thread() {@Overridepublic void run() {Looper.prepare();Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出。\n"+msg, Toast.LENGTH_LONG).show();Looper.loop();}}.start();// 收集设备信息collectCrashDeviceInfo(mContext);// 保存错误报告文件saveCrashInfoToFile(ex);// 发送错误报告到服务器return true;}/** * 保存错误信息到文件中 *  * @param ex * @return */private void saveCrashInfoToFile(Throwable ex) {Writer info = new StringWriter();PrintWriter printWriter = new PrintWriter(info);ex.printStackTrace(printWriter);Throwable cause = ex.getCause();while (cause != null) {cause.printStackTrace(printWriter);cause = cause.getCause();}String result = info.toString();printWriter.close();mDeviceCrashInfo.put(STACK_TRACE, result);try {long timestamp = System.currentTimeMillis();String fileName = "crash-" + timestamp + CRASH_REPORTER_EXTENSION;File file = new File(Constant.StorageLocation_CRASH+File.separator+fileName);if(!file.getParentFile().exists()){file.getParentFile().mkdirs();}FileOutputStream trace = new FileOutputStream(file);mDeviceCrashInfo.store(trace, "");trace.flush();trace.close();} catch (Exception e) {Log.e(TAG, "an error occured while writing report file...", e);}}/** * 收集程序崩溃的设备信息 * @param ctx */public void collectCrashDeviceInfo(Context ctx) {PackageInfo versionInfo = Utils.getVersionInfo(ctx);mDeviceCrashInfo.put(VERSION_NAME, new String(versionInfo.versionName).trim());mDeviceCrashInfo.put(VERSION_CODE, new String(Integer.toString(versionInfo.versionCode)).trim());mDeviceCrashInfo.put(OS_VER, new String(Build.VERSION.RELEASE).trim());mDeviceCrashInfo.put(Device_TYPE, new String(Build.MODEL).trim());}}

如果想全局的接收异常,每个应用对应唯一的Application,我们就应该注册这个application的UncaughtExceptionHandler。

SPZApplication 

Application里面有一个List<Activity>,是存储用来结束所有的Activity的,也用过System.exit(1);等等方式,都不理想,这些方法只能结束一个Activity

public class SPZApplication extends Application {private List<Activity> activityList = new LinkedList<Activity>();private static SPZApplication instance;// 单例模式中获取唯一的MyApplication实例public static SPZApplication getInstance() {return instance;}// 添加Activity到容器中public void addActivity(Activity activity) {activityList.add(activity);}// 遍历所有Activity并finishpublic void exit() {for (Activity activity : activityList) {if(!activity.isFinishing()){activity.finish();}}}@Overridepublic void onCreate() {super.onCreate();instance=this;ExceptionHandler exceptionHandler = ExceptionHandler.getInstance();// 注册crashHandlerexceptionHandler.init(getApplicationContext());// 发送以前没发送的报告(可选)// exceptionHandler.sendPreviousReportsToServer();}}

manifest.xml中的注册:

<application        android:allowBackup="true"        android:icon="@drawable/showicon"        android:label="@string/app_name"        android:name="com.lock.activity.SPZApplication"        android:theme="@style/AppTheme" >        <activity            android:name="com.bpo.lock.activity.CheckActivity"            android:label="@string/app_name"            android:screenOrientation="portrait" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity></application>



0 0
原创粉丝点击