CrashHandler 介绍
Android 应用不可避免的会发生crash 即崩溃,无论程序写的多好,都会不可避免的发生崩溃,可能是由底层引起的,也有可能是写的代码引起的。当crash发生时,系统会kill掉正在执行的程序,现象是程序闪退或提升用户已停止运行。出现这种情况,开发者却无法得到程序为何crash。Android 提供了处理这类问题的方法。
java的Thread中有一个UncaughtExceptionHandler接口,该接口的作用主要是为 了 当 Thread 因未捕获的异常而突然终止时,调用处理程序。
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {// Android-removed: SecurityManager stubbed out on Android./*SecurityManager sm = System.getSecurityManager();if (sm != null) {sm.checkPermission(new RuntimePermission("setDefaultUncaughtExceptionHandler"));}*/defaultUncaughtExceptionHandler = eh;}public interface UncaughtExceptionHandler {/*** Method invoked when the given thread terminates due to the* given uncaught exception.* <p>Any exception thrown by this method will be ignored by the* Java Virtual Machine.* @param t the thread* @param e the exception*/void uncaughtException(Thread t, Throwable e);}
使用
public class CrashHandler implements Thread.UncaughtExceptionHandler {public static final String TAG = "CrashHandler";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 static CrashHandler mInstance;private Context mContext;private Thread.UncaughtExceptionHandler mDefaultCrashHandler;public CrashHandler() {}public static synchronized CrashHandler getInstance() {if (mInstance == null) {synchronized (CrashHandler.class) {if (mInstance == null) {mInstance = new CrashHandler();}}}return mInstance;}public void init(Context context) {mDefaultCrashHandler = Thread.getDefaultUncaughtExceptionHandler();Thread.setDefaultUncaughtExceptionHandler(this);mContext = context.getApplicationContext();}/*** 当程序中有未被捕获的异常,系统将会自动调用uncaughtException方法** @param thread 为出现未捕获异常的线程* @param ex 为未捕获的异常*/@Overridepublic void uncaughtException(@NonNull Thread thread, @NonNull Throwable ex) {try {//导出异常信息到SDCard中dumpExceptionToSDCard(ex);uploadExceptionToServer();} catch (IOException e) {e.printStackTrace();}ex.printStackTrace();//如果系统提供了默认异常处理器,则交给系统去结束程序,否则就由自己结束自己if (mDefaultCrashHandler != null) {mDefaultCrashHandler.uncaughtException(thread, ex);} else {Process.killProcess(Process.myPid());}}private void dumpExceptionToSDCard(Throwable ex) throws IOException {//判断SD是否存在if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {//判断是否是DebugLog.w(TAG, "sdcard unmounted dump exception");return;}File dir = new File(PATH);if (!dir.exists()) {dir.mkdirs();}long currentTimeMillis = System.currentTimeMillis();String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(currentTimeMillis);File file = new File(PATH + FILE_NAME + time + FILE_NAME_SUFFIX);Log.i(TAG, "fileName:" + file.getName() + " , path:" + file.getPath());try {PrintWriter printWriter = new PrintWriter(new BufferedWriter(new FileWriter(file)));printWriter.println(time);dumpPhoneInfo(printWriter);printWriter.println();ex.printStackTrace(printWriter);printWriter.close();} catch (Exception e) {Log.e(TAG, "dump crash info failed");e.printStackTrace();}}private void dumpPhoneInfo(PrintWriter printWriter) throws PackageManager.NameNotFoundException {PackageManager pm = mContext.getPackageManager();PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);printWriter.print("App Version: ");printWriter.print(pi.versionName);printWriter.print("_");printWriter.println(pi.versionCode);//Android 版本号printWriter.print("OS Version: ");printWriter.print(Build.VERSION.RELEASE);printWriter.print("_");printWriter.println(Build.VERSION.SDK_INT);//手机制造商printWriter.print("Vendor: ");printWriter.println(Build.MANUFACTURER);//手机型号printWriter.print("Model: ");printWriter.println(Build.MODEL);//CPU架构printWriter.print("CPU ABI: ");printWriter.println(Build.CPU_ABI);}private void uploadExceptionToServer() {// TODO upload Exception Message To Your Server}
}
在Applicaption 类中初始化
public class TestApplication extends Application {@Overridepublic void onCreate() {super.onCreate();context = getApplicationContext();CrashHandler instance = CrashHandler.getInstance();instance.init(this);}
}
自己手动抛出一个异常
addDisposable(RxView.clicks(mainBinding.settingIv).throttleFirst(PDAConstant.CLICK, TimeUnit.SECONDS).subscribe(o -> {throw new RuntimeException(" 自定义 exception");}));