[Android]Android apk崩溃捕获异常保存到本地(捕获线程异常)

前段时间又温习了下Java,发现了一只野生的UncaughtExceptionHandler,以前居然没发现

从JDK1.5版本开始,加强了对线程的异常处理,如果线程没有捕获异常,那么Java虚拟机会寻找相关的UncaughtExceptionHandler实例,如果找到就调用它的uncaughtException(Thread t, Throwable e)方法。

在Thread类中提供了一个公共的静态的UncaughtExceptionHandler内部接口,负责处理线程未捕获的异常,它的唯一方法是uncaughtException(Thread t, Throwable e),t表示抛出异常的线程,e表示具体的异常。

Thread类提供两个设置异常处理类的方法:

setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)

setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler e)

第一个方法是静态方法,设置线程类的默认异常处理器,第二个是实例方法,设置线程实例的当前异常处理器;

Android中如果要把日志写到SD卡中记得加android.permission.WRITE_EXTERNAL_STORAGE权限


要在application里初始化

CrashHandler handler = CrashHandler.getInstance();
handler.init(this);



代码:

package com.peak.excatch;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.os.Environment;
import android.util.Log;

public class CrashHandler implements UncaughtExceptionHandler {
	private static final String TAG = "CrashHandler";

	private static final boolean DEBUG = true;

	private static final String PATH = Environment.getExternalStorageDirectory().getPath()+"/exceptionCatch/log/";

	private static final String FILE_NAME = "catch";

	private static final String FLIE_NAME_SUFFIX = ".log";

	private UncaughtExceptionHandler mDefaultCrashHandler;

	private Context mContext;

	public CrashHandler() {

	}

	/**
	 * 静态内部类单例
	 * @return
	 */
	public static CrashHandler getInstance(){
		Log.d(TAG, "get crash instance.");
		return InstanceHolder.sInstance;
	}

	private static class InstanceHolder{
		private static CrashHandler sInstance = new CrashHandler();
	}

	public void init(Context context){
		Log.d(TAG, "init UncaughtExceptionnHandler");
		mDefaultCrashHandler = Thread.getDefaultUncaughtExceptionHandler();
		Thread.setDefaultUncaughtExceptionHandler(this);
		mContext = context.getApplicationContext();
	}

	/** 
	 * 程序崩溃会调用该方法 
	 */ 
	@Override
	public void uncaughtException(Thread thread, Throwable ex) {
		try{
			Log.d(TAG, "uncaughtException ...");
			dumpExceptionToSDCard(ex);
			// uploadExceptionToServer(ex);  需要把异常上传到服务器,编写逻辑 解除该行注释 
		}catch(IOException e){
			e.printStackTrace();
		}
	}

	private void dumpExceptionToSDCard(final Throwable ex) throws IOException{
		if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
			if(DEBUG){
				Log.w(TAG, "sdcard unmounted,skip dump exception");
				return;
			}
		}

		File dir = new File(PATH);
		if(!dir.exists()){
			Log.d(TAG, "log dir not exists. ready create");
			dir.mkdirs();

		}

		long current = System.currentTimeMillis();
		final String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(current));
		final File file = new File(PATH + FILE_NAME + FLIE_NAME_SUFFIX);
		new Thread(new Runnable() {

			@Override
			public void run() {
				try{
					PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file)));
					pw.println(time);
					dumpPhoneInfo(pw,ex);
					pw.close();
				}catch(Exception e){
					Log.e(TAG, "dump crash info failed : " + Log.getStackTraceString(e));
				}
			}
		}).start();
	}

	private void dumpPhoneInfo(PrintWriter pw, Throwable ex)throws NameNotFoundException {
		Log.d(TAG, "dumpPhoneInfo ... start");
		PackageManager pm = mContext.getPackageManager();
		PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(),PackageManager.GET_ACTIVITIES);
		pw.print("App version: ");
		pw.print(pi.versionName);
		pw.print('_');
		pw.println(pi.versionCode);

		//Android版本号
		pw.print("OS Version: ");
		pw.print(Build.VERSION.RELEASE);
		pw.print(" _ sdk: ");
		pw.println(Build.VERSION.SDK_INT);

		//手机制造商 
		pw.print("Vendor: ");
		pw.println(Build.MANUFACTURER);

		//手机型号  
		pw.print("Model: ");
		pw.println(Build.MODEL);

		//CPU架构  
		pw.print("CPU ABI : ");
		pw.println(Build.CPU_ABI);
		pw.println();
		//异常信息  
		ex.printStackTrace(pw);


	}

	private void uploadExceptionToServer(Throwable ex){
		//上传到服务器逻辑代码 
	}

}


你可能感兴趣的:(Android开发,android,异常,apk)