虚位以待(AD)
虚位以待(AD)
首页 > 软件编程 > Android编程 > Android编程实现捕获程序异常退出时的错误log信息功能详解

Android编程实现捕获程序异常退出时的错误log信息功能详解
类别:Android编程   作者:码皇   来源:互联网   点击:

这篇文章主要介绍了Android编程实现捕获程序异常退出时的错误log信息功能,结合实例形式分析了Android异常信息捕获与日志操作相关实现技巧,需要的朋友可以参考下

本文实例讲述了Android编程实现捕获程序异常退出时的错误log信息功能。分享给大家供大家参考,具体如下:

很多时候我们程序无缘无故的就挂掉了,让我们一头雾水,如果刚好我们在调试,那我们可以通过错误log来查看是什么原因引起的程序崩溃。但是当我们把程序发别人使用时,就没那么好运了,那我们要怎么样才能捕获到那个错误异常呢?还好Android给我们提供了UncaughtExceptionHandler 这个类,我们可以通过实现这个类的接口,来全局捕获那个让程序崩掉的错误log信息。可以将错误的log保存在本地,也可以发送给服务器后台。下面来看下UncaughtExceptionHandler 的实现类CrashHandler吧。

CrashHandler.Java

    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.io.StringWriter;
    import java.io.Writer;
    import java.lang.Thread.UncaughtExceptionHandler;
    import java.lang.reflect.Field;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Locale;
    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.os.Looper;
    import android.util.Log;
    import android.widget.Toast;
    public class CrashHandler implements UncaughtExceptionHandler {
    private static final String TAG = CrashHandler.class.getSimpleName();
    private static final String SINGLE_RETURN = "n";
    private static final String SINGLE_LINE = "--------------------------------";
    private static CrashHandler mCrashHandler;
    private Context mContext;
    private UncaughtExceptionHandler mDefaultHandler;
    private StringBuffer mErrorLogBuffer = new StringBuffer();
    /** * 获取CrashHandler实例,单例模式。 * * @return 返回CrashHandler实例 */ public static CrashHandler getInstance() {
    if (mCrashHandler == null) {
    synchronized (CrashHandler.class) {
    if (mCrashHandler == null) {
    mCrashHandler = new CrashHandler();
    }
    }
    }
    return mCrashHandler;
    }
    public void init(Context context) {
    mContext = context;
    // 获取系统默认的uncaughtException处理类实例 mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
    // 设置成我们处理uncaughtException的类 Thread.setDefaultUncaughtExceptionHandler(this);
    }
    @Override public void uncaughtException(Thread thread, Throwable ex) {
    Log.d(TAG, "uncaughtException:" + ex);
    if (!handleException(ex) && mDefaultHandler != null) {
    // 如果用户没有处理异常就由系统默认的异常处理器来处理 mDefaultHandler.uncaughtException(thread, ex);
    }
    else {
    try {
    Thread.sleep(3000);
    }
    catch (InterruptedException e) {
    e.printStackTrace();
    }
    android.os.Process.killProcess(android.os.Process.myPid());
    }
    }
    //处理异常事件 private boolean handleException(Throwable ex) {
    if (ex == null) {
    return false;
    }
    new Thread(new Runnable() {
    @Override public void run() {
    Looper.prepare();
    Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出.", Toast.LENGTH_SHORT) .show();
    Looper.loop();
    }
    }
    ).start();
    // 收集设备参数信息 collectDeviceInfo(mContext);
    // 收集错误日志 collectCrashInfo(ex);
    // 保存错误日志 saveErrorLog();
    //TODO: 这里可以加一个网络的请求,发送错误log给后台// sendErrorLog();
    return true;
    }
    //保存日志到/mnt/sdcard/AppLog/目录下,文件名已时间yyyy-MM-dd_hh-mm-ss.log的形式保存 private void saveErrorLog() {
    if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh-mm-ss", Locale.getDefault());
    String format = sdf.format(new Date());
    format += ".log";
    String path = Environment.getExternalStorageDirectory().getPath()+"/AppLog/";
    File file = new File(path);
    if (!file.exists()){
    file.mkdirs();
    }
    FileOutputStream fos = null;
    try {
    fos = new FileOutputStream(path+format);
    fos.write(mErrorLogBuffer.toString().getBytes());
    fos.flush();
    }
    catch (FileNotFoundException e) {
    e.printStackTrace();
    }
    catch (IOException e) {
    e.printStackTrace();
    }
    finally {
    if (fos != null) {
    try {
    fos.close();
    fos = null;
    }
    catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    }
    //收集错误信息 private void collectCrashInfo(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();
    //将错误信息加入mErrorLogBuffer中 append("", result);
    mErrorLogBuffer.append(SINGLE_LINE + SINGLE_RETURN);
    Log.d(TAG, "saveCrashInfo2File:" + mErrorLogBuffer.toString());
    }
    //收集应用和设备信息 private void collectDeviceInfo(Context context) {
    //每次使用前,清掉mErrorLogBuffer里的内容 mErrorLogBuffer.setLength(0);
    mErrorLogBuffer.append(SINGLE_RETURN + SINGLE_LINE + SINGLE_RETURN);
    //获取应用的信息 PackageManager pm = context.getPackageManager();
    try {
    PackageInfo pi = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES);
    if (pi != null) {
    append("versionCode", pi.versionCode);
    append("versionName", pi.versionName);
    append("packageName", pi.packageName);
    }
    }
    catch (NameNotFoundException e) {
    e.printStackTrace();
    }
    mErrorLogBuffer.append(SINGLE_LINE + SINGLE_RETURN);
    //获取设备的信息 Field[] fields = Build.class.getDeclaredFields();
    getDeviceInfoByReflection(fields);
    fields = Build.VERSION.class.getDeclaredFields();
    getDeviceInfoByReflection(fields);
    mErrorLogBuffer.append(SINGLE_LINE + SINGLE_RETURN);
    }
    //获取设备的信息通过反射方式 private void getDeviceInfoByReflection(Field[] fields) {
    for (Field field : fields) {
    try {
    field.setAccessible(true);
    append(field.getName(), field.get(null));
    }
    catch (IllegalArgumentException e) {
    e.printStackTrace();
    }
    catch (IllegalAccessException e) {
    e.printStackTrace();
    }
    }
    }
    //mErrorLogBuffer添加友好的log信息 private void append(String key, Object value) {
    mErrorLogBuffer.append("" + key + ":" + value + SINGLE_RETURN);
    }
    }

在application中的使用非常简单,只要init就好了,之后我们就只要等异常出现吧。

CrashApplication.java

    import android.app.Application;
    public class CrashApplication extends Application{
    @Override public void onCreate() {
    super.onCreate();
    CrashHandler.getInstance().init(this);
    }
    }

不要忘记在AndroidManifest.xml声明我们的CrashApplication 。

AndroidManifest.xml

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><application android:allowBackup="true" android:name=".CrashApplication" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.example.crashtestdemo.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>

更多关于Android相关内容感兴趣的读者可查看本站专题:《Android开发入门与进阶教程》、《Android调试技巧与常见问题解决方法汇总》、《Android编程之activity操作技巧总结》、《Android操作json格式数据技巧总结》、《Android数据库操作技巧总结》、《Android文件操作技巧汇总》、《Android资源操作技巧汇总》及《Android控件用法总结

希望本文所述对大家Android程序设计有所帮助。

相关热词搜索: Android 捕获 程序 异常 退出 错误 log 信