欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android编程实现捕获程序异常退出时的错误log信息功能详解

程序员文章站 2023-12-14 22:15:46
本文实例讲述了android编程实现捕获程序异常退出时的错误log信息功能。分享给大家供大家参考,具体如下: 很多时候我们程序无缘无故的就挂掉了,让我们一头雾水,如果刚好...

本文实例讲述了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程序设计有所帮助。

上一篇:

下一篇: