当前位置: 移动技术网 > IT编程>移动开发>Android > Android 全局异常捕获实例详解

Android 全局异常捕获实例详解

2019年07月24日  | 移动技术网IT编程  | 我要评论

华康新富网,三台新闻网,黄梅租房网

android 全局异常捕获

今天就来说说作为程序猿的我们每天都会遇到的东西bug,出bug不可怕可怕的是没有出bug时的堆栈信息,那么对于bug的信息收集就显得尤为重要了,一般用第三方bugly或者友盟等等都能轻易收集,但是由于公司不让使用第三方,而安卓正好有原生的异常收集类uncaughtexceptionhandler,那么今天博客就从这个类开始.

uncaughtexceptionhandler见名知意,即他是处理我们未捕获的异常,具体使用分两步

1.实现我们自己的异常处理类

public class crashhandler implements thread.uncaughtexceptionhandler {
  @override
  public void uncaughtexception(thread thread, throwable ex) {

  }
}

需要我们实现thread.uncaughtexceptionhandler接口当有未捕获的异常的时候会回调uncaughtexception(thread thread, throwable ex)方法

2.设置该crashhandler为系统默认的

thread.setdefaultuncaughtexceptionhandler(crashhandler);

以上只是使用步骤的介绍,具体项目中的使用我直接贴代码

在application中初始化

package com.zly.www.basedemo.base;

import android.app.application;
import android.content.context;
import com.zly.www.basedemo.exception.crashhandler;

/**
 * created by zly on 2016/6/11.
 */
public class appapplication extends application {


  private static context mcontext;

  @override
  public void oncreate() {
    super.oncreate();
    this.mcontext = this;
    crashhandler.getinstance().init(this);//初始化全局异常管理
  }

  public static context getcontext(){
    return mcontext;
  }
}

crashhandler 实现类如下

package com.zly.www.basedemo.exception;

import android.content.context;
import android.content.pm.packageinfo;
import android.content.pm.packagemanager;
import android.os.build;
import android.os.environment;
import android.os.looper;
import android.util.log;
import android.widget.toast;

import com.zly.www.basedemo.utils.appmanager;

import java.io.file;
import java.io.fileoutputstream;
import java.io.printwriter;
import java.io.stringwriter;
import java.io.writer;
import java.lang.reflect.field;
import java.text.simpledateformat;
import java.util.date;
import java.util.hashmap;
import java.util.map;

/**
 * 全局异常捕获
 * created by zly on 2016/7/3.
 */
public class crashhandler implements thread.uncaughtexceptionhandler {

  /**
   * 系统默认uncaughtexceptionhandler
   */
  private thread.uncaughtexceptionhandler mdefaulthandler;

  /**
   * context
   */
  private context mcontext;

  /**
   * 存储异常和参数信息
   */
  private map<string,string> paramsmap = new hashmap<>();

  /**
   * 格式化时间
   */
  private simpledateformat format = new simpledateformat("yyyy-mm-dd-hh-mm-ss");

  private string tag = this.getclass().getsimplename();

  private static crashhandler minstance;

  private crashhandler() {

  }

  /**
   * 获取crashhandler实例
   */
  public static synchronized crashhandler getinstance(){
    if(null == minstance){
      minstance = new crashhandler();
    }
    return minstance;
  }

  public void init(context context){
    mcontext = context;
    mdefaulthandler = thread.getdefaultuncaughtexceptionhandler();
    //设置该crashhandler为系统默认的
    thread.setdefaultuncaughtexceptionhandler(this);
  }

  /**
   * uncaughtexception 回调函数
   */
  @override
  public void uncaughtexception(thread thread, throwable ex) {
    if(!handleexception(ex) && mdefaulthandler != null){//如果自己没处理交给系统处理
      mdefaulthandler.uncaughtexception(thread,ex);
    }else{//自己处理
      try {//延迟3秒杀进程
        thread.sleep(3000);
      } catch (interruptedexception e) {
        log.e(tag, "error : ", e);
      }
      //退出程序
      appmanager.getappmanager().appexit(mcontext);
    }

  }

  /**
   * 收集错误信息.发送到服务器
   * @return 处理了该异常返回true,否则false
   */
  private boolean handleexception(throwable ex) {
    if (ex == null) {
      return false;
    }
    //收集设备参数信息
    collectdeviceinfo(mcontext);
    //添加自定义信息
    addcustominfo();
    //使用toast来显示异常信息
    new thread() {
      @override
      public void run() {
        looper.prepare();
        toast.maketext(mcontext, "程序开小差了呢..", toast.length_short).show();
        looper.loop();
      }
    }.start();
    //保存日志文件
    savecrashinfo2file(ex);
    return true;
  }


  /**
   * 收集设备参数信息
   * @param ctx
   */
  public void collectdeviceinfo(context ctx) {
    //获取versionname,versioncode
    try {
      packagemanager pm = ctx.getpackagemanager();
      packageinfo pi = pm.getpackageinfo(ctx.getpackagename(), packagemanager.get_activities);
      if (pi != null) {
        string versionname = pi.versionname == null ? "null" : pi.versionname;
        string versioncode = pi.versioncode + "";
        paramsmap.put("versionname", versionname);
        paramsmap.put("versioncode", versioncode);
      }
    } catch (packagemanager.namenotfoundexception e) {
      log.e(tag, "an error occured when collect package info", e);
    }
    //获取所有系统信息
    field[] fields = build.class.getdeclaredfields();
    for (field field : fields) {
      try {
        field.setaccessible(true);
        paramsmap.put(field.getname(), field.get(null).tostring());
      } catch (exception e) {
        log.e(tag, "an error occured when collect crash info", e);
      }
    }
  }

  /**
   * 添加自定义参数
   */
  private void addcustominfo() {

  }

  /**
   * 保存错误信息到文件中
   *
   * @param ex
   * @return 返回文件名称,便于将文件传送到服务器
   */
  private string savecrashinfo2file(throwable ex) {

    stringbuffer sb = new stringbuffer();
    for (map.entry<string, string> entry : paramsmap.entryset()) {
      string key = entry.getkey();
      string value = entry.getvalue();
      sb.append(key + "=" + value + "\n");
    }

    writer writer = new stringwriter();
    printwriter printwriter = new printwriter(writer);
    ex.printstacktrace(printwriter);
    throwable cause = ex.getcause();
    while (cause != null) {
      cause.printstacktrace(printwriter);
      cause = cause.getcause();
    }
    printwriter.close();
    string result = writer.tostring();
    sb.append(result);
    try {
      long timestamp = system.currenttimemillis();
      string time = format.format(new date());
      string filename = "crash-" + time + "-" + timestamp + ".log";
      if (environment.getexternalstoragestate().equals(environment.media_mounted)) {
        string path = environment.getexternalstoragedirectory().getabsolutepath() + "/crash/";
        file dir = new file(path);
        if (!dir.exists()) {
          dir.mkdirs();
        }
        fileoutputstream fos = new fileoutputstream(path + filename);
        fos.write(sb.tostring().getbytes());
        fos.close();
      }
      return filename;
    } catch (exception e) {
      log.e(tag, "an error occured while writing file...", e);
    }
    return null;
  }
}

activity管理类

package com.zly.www.basedemo.utils;

import java.util.stack;

import android.app.activity; 
import android.app.activitymanager; 
import android.content.context;

/**
 * activity管理类:用于管理activity和退出程序
 * created by zly on 2016/6/11.
 */
public class appmanager { 

  // activity栈 
  private static stack<activity> activitystack; 
  // 单例模式 
  private static appmanager instance; 

  private appmanager() { 
  } 

  /** 
   * 单一实例 
   */ 
  public static appmanager getappmanager() { 
    if (instance == null) { 
      instance = new appmanager(); 
    } 
    return instance; 
  } 

  /** 
   * 添加activity到堆栈 
   */ 
  public void addactivity(activity activity) { 
    if (activitystack == null) { 
      activitystack = new stack<activity>(); 
    } 
    activitystack.add(activity); 
  } 

  /** 
   * 获取当前activity(堆栈中最后一个压入的) 
   */ 
  public activity currentactivity() { 
    activity activity = activitystack.lastelement(); 
    return activity; 
  } 

  /** 
   * 结束当前activity(堆栈中最后一个压入的) 
   */ 
  public void finishactivity() { 
    activity activity = activitystack.lastelement(); 
    finishactivity(activity); 
  } 

  /** 
   * 结束指定的activity 
   */ 
  public void finishactivity(activity activity) { 
    if (activity != null) { 
      activitystack.remove(activity); 
      activity.finish(); 
      activity = null; 
    } 
  } 

  /** 
   * 结束指定类名的activity 
   */ 
  public void finishactivity(class<?> cls) { 
    for (activity activity : activitystack) { 
      if (activity.getclass().equals(cls)) { 
        finishactivity(activity);
        break;
      } 
    } 
  } 

  /** 
   * 结束所有activity 
   */ 
  public void finishallactivity() { 
    for (int i = 0; i < activitystack.size(); i++) { 
      if (null != activitystack.get(i)) { 
        activitystack.get(i).finish(); 
      } 
    } 
    activitystack.clear(); 
  } 

  /** 
   * 退出应用程序 
   */ 
  public void appexit(context context) { 
    try { 
      finishallactivity(); 
      //退出程序
      android.os.process.killprocess(android.os.process.mypid());
      system.exit(1); 
    } catch (exception e) { 
    } 
  } 
} 

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网