android 捕捉异常并上传至服务器的简单实现

android 捕捉异常并上传至服务器的简单实现,第1张

概述在项目中,我们的应用经常会遇到崩溃的情况,如果你的项目已经发送到了应用市场上,那么应用发生的崩溃开发人员是开不到的,所以我们要想办法将异常信息传到服务器上,便于开发人员查看并作出修改。Google考虑到这一

在项目中,我们的应用经常会遇到崩溃的情况,如果你的项目已经发送到了应用市场上,那么应用发生的崩溃开发人员是开不到的,所以我们要想办法将异常信息传到服务器上,便于开发人员查看并作出修改。Google考虑到这一点,也提供了Thread.UncaughtExceptionHandler接口来实现这一问题。

创建Crash异常捕获很简单,主要的步骤有:

1.创建BaseApplication继承Application并实现Thread.UncaughtExceptionHandler

2.通过Thread.setDefaultUncaughtExceptionHandler(this)设置默认的异常捕获

3.最后在manifests中注册创建的BaseApplication

一、异常捕捉的简单实用

public class BaseApplication extends Application implements Thread.UncaughtExceptionHandler {  @OverrIDe  public voID onCreate() {    super.onCreate();    //设置异常捕获    CrashHandler catchHandler = CrashHandler.getInstance();    catchHandler.init(this);  }}

二、CrashHandler(主要是实现uncaughtException方法)

public class CrashHandler implements UncaughtExceptionHandler {  public static final String TAG = "CrashHandler";  // 系统默认的UncaughtException处理类  private Thread.UncaughtExceptionHandler mDefaultHandler;  // CrashHandler实例  private static CrashHandler instance;  // 程序的Context对象  private Context mContext;  // 用来存储设备信息和异常信息  private Map<String,String> infos = new HashMap<String,String>();  // 用于格式化日期,作为日志文件名的一部分  private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");  MyActivitylifecycleCallbacks mMyActivitylifecycleCallbacks = new MyActivitylifecycleCallbacks();  /** 保证只有一个CrashHandler实例 */  private CrashHandler() {  }  /** 获取CrashHandler实例,单例模式 */  public static CrashHandler getInstance() {    if (instance == null)      instance = new CrashHandler();    return instance;  }  /**   * 初始化   */  public voID init(sspApplication context) {    mContext = context;    context.registeractivitylifecycleCallbacks(mMyActivitylifecycleCallbacks);    // 获取系统默认的UncaughtException处理器    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 {    //    Thread.sleep(3000);    //  } catch (InterruptedException e) {    //    Log.e(TAG,"error : ",e);    //  }    // 注意Thread.sleep(3000)和 SystemClock.sleep(3000)的区别      SystemClock.sleep(3000);      // 退出程序      Log.i("=====killProcess======","=====killProcess======");      mMyActivitylifecycleCallbacks.removeAllActivitIEs();      androID.os.Process.killProcess(androID.os.Process.myPID());      System.exit(0);    }  }  /**   * 自定义错误处理,收集错误信息 发送错误报告等 *** 作均在此完成.   *    * @param ex   * @return true:如果处理了该异常信息;否则返回false.   */  private boolean handleException(Throwable ex) {    Log.i("=====handleException======","=====handleException======");    if (ex == null) {      return false;    }    // 收集设备参数信息    collectDeviceInfo(mContext);    // 使用Toast来显示异常信息    new Thread() {      @OverrIDe      public voID run() {        Looper.prepare();        Toast.makeText(mContext,"哎呀,出问题了,我要暂时离开了",Toast.LENGTH_SHORT).show();        Looper.loop();      }    }.start();    // 保存日志文件    saveCatchInfo2file(ex);    return true;  }  /**   * 收集设备参数信息   *    * @param ctx   */  public voID collectDeviceInfo(Context ctx) {    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 + "";        infos.put("versionname",versionname);        infos.put("versionCode",versionCode);      }    } catch (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);        infos.put(fIEld.getname(),fIEld.get(null).toString());        Log.d(TAG,fIEld.getname() + " : " + fIEld.get(null));      } catch (Exception e) {        Log.e(TAG,"an error occured when collect crash info",e);      }    }  }  /**   * 保存错误信息到文件中   *    * @param ex   * @return 返回文件名称,便于将文件传送到服务器   */  private String saveCatchInfo2file(Throwable ex) {    StringBuffer sb = new StringBuffer();    for (Map.Entry<String,String> entry : infos.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 = formatter.format(new Date());      SharedPreferences userInfo = mContext.getSharedPreferences(          Constants.USER_SETTING_INFOS,0);      String loginname = userInfo.getString(Constants.USERname,"");      String filename = "crash-" + time +"-"+loginname+ ".log";      if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {        String path = "/mnt/sdcard/crash/";        file dir = new file(path);        if (!dir.exists()) {          dir.mkdirs();        }        fileOutputStream fos = new fileOutputStream(path + filename);        fos.write(sb.toString().getBytes());        // 发送给开发人员        sendCrashLog2PM(path + filename);        fos.close();      }      return filename;    } catch (Exception e) {      Log.e(TAG,"an error occured while writing file...",e);    }    return null;  }  /**   * 将捕获的导致崩溃的错误信息发送给开发人员   *    * 目前只将log日志保存在sdcard 和输出到LogCat中,并未发送给后台。   */  private voID sendCrashLog2PM(final String filename) {    if (!new file(filename).exists()) {      Toast.makeText(mContext,"日志文件不存在!",Toast.LENGTH_SHORT).show();      return;    } else {        new Thread(new Runnable() {        @OverrIDe        public voID run() {          Looper.prepare();          ArrayList<String> picList = new ArrayList<String>();          picList.add(filename);          SendEventPic sfile = new SendEventPic(mContext);          UUIDGenerator generator = new UUIDGenerator();          String linkID = generator.generate().toString();          SharedPreferences userInfo = mContext.getSharedPreferences(              Constants.USER_SETTING_INFOS,0);          String loginname = userInfo.getString(Constants.USERname,"");          String userID = userInfo.getString(Constants.USER_USERID_INFOS,"");          boolean isproblempic = sfile.isSendSuccess(picList,linkID,"crash_tng",loginname,userID);          Looper.loop();        }      }).start();    }    fileinputStream fis = null;    BufferedReader reader = null;    String s = null;    try {      fis = new fileinputStream(filename);      reader = new BufferedReader(new inputStreamReader(fis,"GBK"));      while (true) {        s = reader.readline();        if (s == null)          break;        // 由于目前尚未确定以何种方式发送,所以先打出log日志。        Log.i("info",s.toString());      }    } catch (fileNotFoundException e) {      e.printstacktrace();    } catch (IOException e) {      e.printstacktrace();    } finally { // 关闭流      try {        reader.close();        fis.close();      } catch (IOException e) {        e.printstacktrace();      }    }  }}

三、开发过程中遇到的坑

如果在activity创建的时候崩溃的话,系统有时候(目前不确定什么情况下会重启)会重启当前的activity,造成第二次的崩溃,如此循环……

所以,在应用崩溃时要完全退出应用。

public class MyActivitylifecycleCallbacks implements ActivitylifecycleCallbacks {  private List<Activity> activitIEs = new linkedList<>();  public static int sAnimationID = 0;  @OverrIDe  public voID onActivityCreated(Activity activity,Bundle savedInstanceState) {    addActivity(activity);  }  @OverrIDe  public voID onActivityStarted(Activity activity) {  }  @OverrIDe  public voID onActivityResumed(Activity activity) {  }  @OverrIDe  public voID onActivityPaused(Activity activity) {  }  @OverrIDe  public voID onActivityStopped(Activity activity) {  }  @OverrIDe  public voID onActivitySaveInstanceState(Activity activity,Bundle outState) {  }  @OverrIDe  public voID onActivityDestroyed(Activity activity) {    removeActivity(activity);  }  /**   * 添加Activity   */  public voID addActivity(Activity activity) {    if (activitIEs == null) {      activitIEs = new linkedList<>();    }    if (!activitIEs.contains(activity)) {      activitIEs.add(activity);// 把当前Activity添加到集合中    }  }  /**   * 移除Activity   */  public voID removeActivity(Activity activity) {    if (activitIEs.contains(activity)) {      activitIEs.remove(activity);    }    if (activitIEs.size() == 0) {      activitIEs = null;    }  }  /**   * 销毁所有activity   */  public voID removeAllActivitIEs() {    for (Activity activity : activitIEs) {      if (null != activity) {        activity.finish();        activity.overrIDePendingTransition(0,sAnimationID);      }    }  }}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

总结

以上是内存溢出为你收集整理的android 捕捉异常并上传至服务器的简单实现全部内容,希望文章能够帮你解决android 捕捉异常并上传至服务器的简单实现所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1146369.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存