Android之用UncaughtExceptionHandler实现保存崩溃日志到sdcard目录下的文件夹

来源:互联网 发布:淘宝erp系统 编辑:程序博客网 时间:2024/06/05 19:42

1、异常和UncaughtExceptionHandler的介绍

1)、Java异常处理机制中:
如果抛出的是Exception异常的话,需要有try catch进行处理,属于可以捕获exception。
如果抛出的是RuntimeException异常的话,发生异常之后将由JVM进行处理,属于不可捕获exception。


2)、Java 异常的分类:
基类为:Throwable
Error 和 Exception 继承于Throwable
RuntimeException和IOException等继承Exception
其中,Error和RuntimeException及其子类属于不可捕获exception,而其他异常为可捕获exception
RuntimeExcption体系,包括错误的类型转换,数组越界访问和试图访问空指针等


3)、在Android开发中,常常会出现不可捕获  导致程序的crash,为了提供良好的用户体验,常使用Thread.UncaughtExceptionHandler来进行处理,可以实现崩溃日志保存到本地,也可以上传到服务端
UncaughtExceptionHandler接口,该接口的作用主要是为了  当 Thread 因未捕获的异常而突然终止时,调用处理程序
接口下面有setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
方法,方法主要作用为设置当线程由于未捕获到异常而突然终止,并且没有为该线程定义其他处理程序时所调用的默认处理程序,
一个类实现UncaughtExceptionHandler接口,出现崩溃会回调UncaughtException方法



2、实现崩溃日志保存到sdcard目录下的“chenyu”文件夹

CrashHandler.java文件如下
package com.example.crashhandler;import java.io.BufferedWriter;import java.io.File;import java.io.FileWriter;import java.io.IOException;import java.io.PrintWriter;import java.io.StringWriter;import java.io.Writer;import java.lang.Thread.UncaughtExceptionHandler;import java.text.SimpleDateFormat;import java.util.Date;import java.util.HashMap;import java.util.Map;import android.content.Context;import android.content.pm.PackageInfo;import android.content.pm.PackageManager;import android.content.pm.PackageManager.NameNotFoundException;import android.os.Environment;import android.os.Looper;import android.util.Log;import android.widget.Toast;public class CrashHandler implements UncaughtExceptionHandler {public static String TAG = "CrashHandler";public Context mContext;public static final String CRASH = "I has crash";public static final String VERSION_NAME = "versionName";public static final String VERSION_CODE = "versionCode";public static final String PACKAGE_NAME = "packageName";public static final String PHONE_TYPE = "phoneType";public static final String SYSTEM_VERSION = "systemVersion";public static final String ANDROID_VERSION = "androidVersion";public CrashHandler(Context context) {this.mContext = context;}public CrashHandler() {}@Overridepublic void uncaughtException(Thread thread, Throwable ex) {Log.d(TAG, "uncaughtException");ex.printStackTrace();int id = (int) thread.getId();//UI Thread id is 1Log.d(TAG, "crash Thread id " + id);if (id == 1) {Log.d(TAG, "crash Thread is UI thread");} else {Log.d(TAG, "crash Thread is not UI thread");}//get phone and crash informationString crashInfo = getAllInfo(ex, getInfo());//save crash file boolean result = saveCrashToFile(crashInfo);if (result) {Log.d(TAG, "save crash file success");} else {Log.d(TAG, "save crash file fail");}//send crash file to ServershowError();}public void showError() {Log.d(TAG, "showErrorQuit");new Thread(new Runnable(){@Overridepublic void run() {Looper.prepare();Toast.makeText(mContext, CRASH, Toast.LENGTH_SHORT).show();Looper.loop();}}).start();try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}android.os.Process.killProcess(android.os.Process.myPid());System.exit(1);}public Map<String, String> getInfo() {if (mContext == null) {return null;}PackageManager pm = mContext.getPackageManager();Map<String, String> map = new HashMap<String, String>();if (pm != null) {PackageInfo pkInfo;try {pkInfo = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);Log.d(TAG, "mContext.getPackageName() is " + mContext.getPackageName());} catch (NameNotFoundException e) {Log.e(TAG, "pm.getPackageInfo fail");return null;}if (pkInfo != null) {map.put(VERSION_NAME, pkInfo.versionName);map.put(VERSION_CODE, pkInfo.versionCode + "");map.put(PACKAGE_NAME, pkInfo.packageName);map.put(PHONE_TYPE, android.os.Build.MODEL);map.put(SYSTEM_VERSION, android.os.Build.VERSION.SDK);map.put(ANDROID_VERSION, android.os.Build.VERSION.RELEASE);;}} else {Log.d(TAG, "package is null");}return map;}public String getAllInfo(Throwable ex, Map<String, String> map) {StringBuffer sb = new StringBuffer();Writer writer = new StringWriter();for (Map.Entry<String, String> entry : map.entrySet()) {sb.append("phone info:" + entry.getKey() + ":" + entry.getValue() + "\n");}PrintWriter pw = new PrintWriter(writer);ex.printStackTrace(pw);Throwable cause =  ex.getCause();if (cause != null) {cause.printStackTrace(pw);cause = cause.getCause();}pw.flush();pw.close();sb.append("Exception is :" + writer.toString() + "---end");Log.d(TAG, sb.toString());return sb.toString();} public boolean saveCrashToFile(String crashInfo) {String current = System.currentTimeMillis() + "";SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");String time = format.format(new Date());String fileName = time + "_"+ current + ".log";//mkdir File folder = new File(Environment.getExternalStorageDirectory().getPath() + "/chenyu");if (!folder.exists())folder.mkdirs();//make crash fileFile crashFile = new File(folder.getAbsolutePath() + File.separator + fileName);try {FileWriter fileWriter = new FileWriter(crashFile);BufferedWriter bw = new BufferedWriter(fileWriter);bw.write(crashInfo);bw.flush();bw.close();} catch (IOException e) {Log.e(TAG, "new FileWriter fail");return false;}return true;}}


MyApplication.java文件如下
package com.example.crashhandler;import java.lang.Thread.UncaughtExceptionHandler;import android.support.v7.app.ActionBarActivity;import android.os.Bundle;import android.view.Menu;import android.view.MenuItem;public class MainActivity extends ActionBarActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);throw new NullPointerException();}}


MyApplication.java文件如下
package com.example.crashhandler;import java.lang.Thread.UncaughtExceptionHandler;import android.app.Application;public class MyApplication extends Application {@Overridepublic void onCreate() { UncaughtExceptionHandler exceptionHandler = Thread.getDefaultUncaughtExceptionHandler();if (exceptionHandler != null) {Thread.setDefaultUncaughtExceptionHandler(new CrashHandler(this));}}}

AndroidManifest.xml文件如下
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.crashhandler"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk        android:minSdkVersion="11"        android:targetSdkVersion="21" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.READ_PHONE_STATE"/>    <application        android:name="com.example.crashhandler.MyApplication"        android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme" >        <activity            android:name=".MainActivity"            android:label="@string/app_name" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>    </application></manifest>




3、查看保存崩溃日志文件的内容结果


adb pull /sdcard/chenyu/vim ***.log






0 0
原创粉丝点击